Reindex array by increasing and decreasing all of top indexes - php

First, I have to list what I have found
How to Remove Array Element and Then Re-Index Array?
PHP reindex array?
They did not make sense in my case. I have fallen into ridiculous request and I've force to find the way out, then please don't ask me why I want to do that.
I have below array
$input = array(
0=>array('a', 'b'=>array('c')),
1=>array('b', 'c'=>array('d')),
2=>array('c', 'd'=>array('e')),
);
I want to increase all of keys by 1 or decrease by 1 (acceptable to index is negative int number)
Here is expected result
//after increased by 1
$input = array(
1=>array('a', 'b'=>array('c')),
2=>array('b', 'c'=>array('d')),
3=>array('c', 'd'=>array('e')),
);
or
//after decreased by 1
$input = array(
-1=>array('a', 'b'=>array('c')),
0=>array('b', 'c'=>array('d')),
1=>array('c', 'd'=>array('e')),
);
The closet answer I got here from raina77ow in the question
How to increase by 1 all keys in an array?
$arr = array_flip(array_map(function($el){ return $el + 1; }, array_flip($arr)));
But it just works with simple array key pairs, if array value is other array instead of a string or integer, it would raise the exception
array_flip(): Can only flip STRING and INTEGER values!
The thing what I could think is handling the array to swap roster manually, it would be the final way if there were not any other workaround.
Any help is appreciated!

This should so the trick.
// Increase by one
$input = array_combine(
array_map(function($value) {
return $value += 1;
}, array_keys($input)), $input
);

The easiest way would probably to use foreach and make a new array... like this:
$new = array();
foreach($arr as $k=>$v) {
$new[$k+1] = $v; // either increase
$new[$k-1] = $v; // or decrease
}
You can also perform the operation by passing the original array by reference.

Related

PHP / json encode wrongly interprets as associative array

Edit1: The problem: I want to convert in php a associative array to a indexed one. So I can return it via json_encode as an array and not as an object. For this I try to fill the missing keys. Here the description:
Got a small problem, I need to transfer a json_encoded array as an array to js. At the moment it returns an Object. I´m working with Angular so I really need an Array. I try to explain it as much as possible.
$arrNew[0][5][0][0][1]["id"] = 1;
//$arrNew[0][0][0][0][1] = "";
//$arrNew[0][1][0][0][1] = "";
//$arrNew[0][2][0][0][1] = "";
//$arrNew[0][3][0][0][1] = "";
//$arrNew[0][4][0][0][1] = "";
$arrNew[0][5][0][0][1]["name"] = 'Test';
var_dump($arrNew);
So if I return it now It returns the second element as object cause of the missing index 0-4 and the 4th element cause of the missing index 0 (associative array -> object)
So if I uncomment the block it works like a charm. Now I have the problem its not every time the element 5 sometime 3, 4 or something else so I build a function which adds them automaticly:
$objSorted = cleanArray($arrNew);
function cleanArray($array){
end($array);
$max = key($array) + 1; //Get the final key as max!
for($i = 0; $i < $max; $i++) {
if(!isset($array[$i])) {
$array[$i] = '';
} else {
end($array[$i]);
$max2 = key($array[$i]) + 1;
for($i2 = 0; $i2 < $max2; $i2++) {
.... same code repeats here for every index
So if I vardump it it returns:
The problem:
On js side its still an object, what I also see is that the elements are not sorted. So I think somehow PHP sees it still as an associative array. Any clue why this happens ? The key is set with the index of the loop and has to be a integer value.
PS: I know reworking it in JS is possible but would have be done nearly on every request with a huge load of loops
If I understand your problem, you create a sparse multidimensional array of objects. Because the arrays have gaps in the keys, json_encode() produces objects on some levels but you need it to produce arrays for all but the most inner level.
The following function fills the missing keys (starting from 0 until the maximum value used as numeric key in an array) on all array levels. It then sorts each array by their keys to make sure json_encode() encodes it as array and not object.
The sorting is needed, otherwise json_encode() generates an object; this behaviour is explained in a note on the json_encode() documentation page:
When encoding an array, if the keys are not a continuous numeric sequence starting from 0, all keys are encoded as strings, and specified explicitly for each key-value pair.
// If $arr has numeric keys (not all keys are tested!) then returns
// an array whose keys are a continuous numeric sequence starting from 0.
// Operate recursively for array values of $arr
function fillKeys(array $arr)
{
// Fill the numeric keys of all values that are arrays
foreach ($arr as $key => $value) {
if (is_array($value)) {
$arr[$key] = fillKeys($value);
}
}
$max = max(array_keys($arr));
// Sloppy detection of numeric keys; it may fail you for mixed type keys!
if (is_int($max)) {
// Fill the missing keys; use NULL as value
$arr = $arr + array_fill(0, $max, NULL);
// Sort by keys to have a continuous sequence
ksort($arr);
}
return $arr;
}
// Some array to test
$arrNew[0][5][0][0][1]["id"] = 1;
$arrNew[0][3][0][2][1]["id"] = 2;
$arrNew[0][5][0][0][1]["name"] = 'Test';
echo("============= Before ==============\n");
echo(json_encode($arrNew)."\n");
$normal = fillKeys($arrNew);
echo("============= After ==============\n");
echo(json_encode($normal)."\n");
The output:
============= Before ==============
[{"5":[[{"1":{"id":1,"name":"Test"}}]],"3":[{"2":{"1":{"id":2}}}]}]
============= After ==============
[[null,null,null,[[null,null,[null,{"id":2}]]],null,[[[null,{"id":1,"name":"Test"}]]]]]
The line $arr = $arr + array_fill(0, $max, NULL); uses NULL as values for the missing keys. This is, I think, the best for the Javascript code that parses the array (you can use if (! arr[0]) to detect the dummy values).
You can use the empty string ('') instead of NULL to get a shorter JSON:
[["","","",[["","",["",{"id":2}]]],"",[[["",{"id":1,"name":"Test"}]]]]]
but it requires slightly longer code on the JS side to detect the dummy values (if (arr[0] != '')).

Swap my element's order to be the first in an array

Let's say I have an array like so:
array(
[0]=>1
[1]=>3
[3]=>5
[15]=>6
);
Arbitrarily I want array[15] to be the first:
array(
[15]=>6
[0]=>1
[1]=>3
[3]=>5
);
What is the fastest and most painless way to do this?
Here are the things I've tried:
array_unshift - Unfortunately, my keys are numeric and I need to keep the order (sort of like uasort) this messes up the keys.
uasort - seems too much overhead - the reason I want to make my element the first in my array is to specifically avoid uasort! (Swapping elements on the fly instead of sorting when I need them)
Assuming you know the key of the element you want to shift, and that element could be in any position in the array (not necessarily the last element):
$shift_key = 15;
$shift = array($shift_key => $arr[$shift_key]);
$arr = $shift + $arr;
See demo
Updated - unset() not necessary. Pointed out by #FuzzyTree
You can try this using a slice and a union operator:
// get last element (preserving keys)
$last = array_slice($array, -1, 1, true);
// put it back with union operator
$array = $last + $array;
Update: as mentioned below, this answer takes the last key and puts it at the front. If you want to arbitrarily move any element to the front:
$array = array($your_desired_key => $array[$your_desired_key]) + $array;
Union operators take from the right and add to the left (so the original value gets overwritten).
If #15 is always last you can do
$last = array_pop($array); //remove from end
array_unshift($last); //push on front
To reorder the keys for sorting simply add
$array = array_values($array); //reindex array
#Edit - if we don't assume its always last then I would go with ( if we always know wwhat the key is, then most likely we will know its position or it's not a numerically indexed array but an associative one with numeric keys, as op did state "arbitrarily" so one has to assume the structure of the array is known before hand. )
I also dont see the need to reindex them as the op stated that it was to avoid sorting. So why would you then sort?
$item = $array[15];
unset($array[15]); //....etc.

fastest way to search first repetitive value in an unsorted integer array of 10 numbers?

What can be the fastest way to search first repetitive value in an unsorted integer array of 10 numbers?
What should be the answer if the array has 10 million records?
The only way i can think of is using 2 array since you want first repetitive value in an unsorted integer
10 million ??? Not sure of memory implication
PHP DOC Comment
Memory footprint of splFixedArray is about 37% of a regular "array" of the same size.
I was hoping for more, but that's also significant, and that's where you should expect to see difference, not in "performance
How big are PHP arrays (and values) really? (Hint: BIG!)
Example
$array = SplFixedArray::fromArray(array(1,2,4,6,4,2,7,7,3,3,1));
$list = array();
foreach ($array as $value ) {
if (in_array($value, $list)) {
echo $value;
break;
}
$list[] = $value;
}
Output
4
If you want the smallest repeated number then
Sort the array with Radix sort in O(n) time
Loop through the sorted array and find the first repeat
If you want the first repeated number in whatever order the array is already in then
Loop through the array adding the numbers to a Hash Set until you reach a number that you can't add to the Hash Set because it's it already exists.
Here is benchmark code. It was too big to fit into comment, so I put it as separate answer.
<?php
$array = range(0, 10000);
$time_start = microtime(true);
$list = array();
foreach ( $array as $value ) {
if (in_array($value, $list)) {
echo $value;
break;
}
$list[] = $value;
}
printf("Using foreach loop:<br/>%0.10f<br/><br/>", microtime(true)-$time_start);
$time_start = microtime(true);
$list = array();
foreach ( new ArrayIterator($array) as $value ) {
if (in_array($value, $list)) {
echo $value;
break;
}
$list[] = $value;
}
printf("Using ArrayIterator:<br/>%0.10f<br/><br/>", microtime(true)-$time_start);
foreach loop is faster than ArrayIterator.
I tried with 10000 elements. Elements were generating with range function, which ensured I have 'the worst' input array, where all elements are different.
With 1 million records array generation took too long on my machine.

Which is the best way to remove middle element of associative array in PHP?

Please tell me which is the best way to unset middle element of associative array in PHP?
Suppose I have an array of 10,000 elements and I want to remove middle element of that array, which is efficient way to remove middle element?
$temp = array('name1'=>'value1','name2'=>'value2',...,'name10000'=>'value10000');
$middleElem = ceil(count($temp) / 2);
$i = 0;
foreach ($temp as $key=>$val) {
if ($i == $middleElem) {
unset($temp[$key]);
break;
}
$i++;
}
Is above code efficient way?
Considering $array is your array, this code remove the middle element if it has odd number of elements. If its event it'll remove the first of 2 middle elements.
$i = round(count($array)/2) - 1;
$keys = array_keys($array);
unset ($array[$keys[$i]]);
Test Result: http://ideone.com/wFEM2
The thing you have to figure out is what you want to do when you have an array with an even number of elements. What element do you want to get then?
The above code picks the 'lower' element, the code could easily be edited to make it pick the 'higher' element. The only thing you have to check is (what all others answers failed to do) what happens if you have three elements. It doesn;t pick the middle element, but the last. So you would have to add a check for that then.
$temp = Array("name1"=>"value1","name2"=>"value2",...,"name10000"=>"value10000");
$middleElem = ceil(count($temp)/2);
$keys = array_keys($temp);
$middleKey = $keys[$middleElem];
unset($temp[$middleKey]);
There ^_^
I think it's a proper way to do it. Try this:
array_remove_at( $temp, ceil(count($temp) / 2) - 1);
function array_remove_at(&$array, $index){
if (array_key_exists($index, $array)) {
array_splice($array, $index, 1);
}
}
You can find the size of the array, divide that number by two and then proceed to remove the element. Not sure about the performance isssues about that though
Firstly, I wouldn't worry too much about what is the most efficient way at this point. You're much better off coding for how easy the code is to read, debug and change. Micro-optimisations like this rarely produce great results (as they're often not the biggest bottlenecks).
Having said that, if you want a solution that is easy to read, then how about using array_splice.
$temp = array('name1'=>'value1','name2'=>'value2',...,'name10000'=>'value10000');
$middleElem = ceil(count($temp) / 2);
array_splice( $temp, $middleElem, 1 );
I would take it that the following code is more efficient, because you don't have to execute it in a loop. I generally follow the same pattern as Kolink, but my version checks if there actually is a "middle element". Works on all types of arrays, I think.
<?php
for( $i = 0; $i <= 9; $i ++ ) {
$temp['name'.$i] = 'value'.$i;
}
if( ( $count = count( $temp ) ) % 2 === 0 ) {
/** Only on uneven arrays. */
array_splice( $temp, ( ceil( $count ) / 2 ), 1 );
}
var_dump( $temp );
EDIT: Thavarith seems to be right; array_splice is much faster than simply unsetting the value. Plus, you get the added benefit of not having to use array_keys, as you already now at what $offset the middle is.
Proper way seems to be:
unset(arr[id]);
arr = array_values(arr);
For first removing element at index id and then re-indexing the array arr properly.
unset($myArray[key])
since your array is associative, you can drop any element easily this way

PHP best way to MD5 multi-dimensional array?

What is the best way to generate an MD5 (or any other hash) of a multi-dimensional array?
I could easily write a loop which would traverse through each level of the array, concatenating each value into a string, and simply performing the MD5 on the string.
However, this seems cumbersome at best and I wondered if there was a funky function which would take a multi-dimensional array, and hash it.
(Copy-n-paste-able function at the bottom)
As mentioned prior, the following will work.
md5(serialize($array));
However, it's worth noting that (ironically) json_encode performs noticeably faster:
md5(json_encode($array));
In fact, the speed increase is two-fold here as (1) json_encode alone performs faster than serialize, and (2) json_encode produces a smaller string and therefore less for md5 to handle.
Edit: Here is evidence to support this claim:
<?php //this is the array I'm using -- it's multidimensional.
$array = unserialize('a:6:{i:0;a:0:{}i:1;a:3:{i:0;a:0:{}i:1;a:0:{}i:2;a:3:{i:0;a:0:{}i:1;a:0:{}i:2;a:0:{}}}i:2;s:5:"hello";i:3;a:2:{i:0;a:0:{}i:1;a:0:{}}i:4;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:0:{}}}}}}}i:5;a:5:{i:0;a:0:{}i:1;a:4:{i:0;a:0:{}i:1;a:0:{}i:2;a:3:{i:0;a:0:{}i:1;a:0:{}i:2;a:0:{}}i:3;a:6:{i:0;a:0:{}i:1;a:3:{i:0;a:0:{}i:1;a:0:{}i:2;a:3:{i:0;a:0:{}i:1;a:0:{}i:2;a:0:{}}}i:2;s:5:"hello";i:3;a:2:{i:0;a:0:{}i:1;a:0:{}}i:4;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:0:{}}}}}}}i:5;a:5:{i:0;a:0:{}i:1;a:3:{i:0;a:0:{}i:1;a:0:{}i:2;a:3:{i:0;a:0:{}i:1;a:0:{}i:2;a:0:{}}}i:2;s:5:"hello";i:3;a:2:{i:0;a:0:{}i:1;a:0:{}}i:4;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:0:{}}}}}}}}}}i:2;s:5:"hello";i:3;a:2:{i:0;a:0:{}i:1;a:0:{}}i:4;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:0:{}}}}}}}}}');
//The serialize test
$b4_s = microtime(1);
for ($i=0;$i<10000;$i++) {
$serial = md5(serialize($array));
}
echo 'serialize() w/ md5() took: '.($sTime = microtime(1)-$b4_s).' sec<br/>';
//The json test
$b4_j = microtime(1);
for ($i=0;$i<10000;$i++) {
$serial = md5(json_encode($array));
}
echo 'json_encode() w/ md5() took: '.($jTime = microtime(1)-$b4_j).' sec<br/><br/>';
echo 'json_encode is <strong>'.( round(($sTime/$jTime)*100,1) ).'%</strong> faster with a difference of <strong>'.($sTime-$jTime).' seconds</strong>';
JSON_ENCODE is consistently over 250% (2.5x) faster (often over 300%) -- this is not a trivial difference. You may see the results of the test with this live script here:
http://nathanbrauer.com/playground/serialize-vs-json.php
http://nathanbrauer.com/playground/plain-text/serialize-vs-json.php
Now, one thing to note is array(1,2,3) will produce a different MD5 as array(3,2,1). If this is NOT what you want. Try the following code:
//Optionally make a copy of the array (if you want to preserve the original order)
$original = $array;
array_multisort($array);
$hash = md5(json_encode($array));
Edit: There's been some question as to whether reversing the order would produce the same results. So, I've done that (correctly) here:
http://nathanbrauer.com/playground/json-vs-serialize.php
http://nathanbrauer.com/playground/plain-text/json-vs-serialize.php
As you can see, the results are exactly the same. Here's the (corrected) test originally created by someone related to Drupal:
http://nathanjbrauer.com/playground/drupal-calculation.php
http://nathanjbrauer.com/playground/plain-text/drupal-calculation.php
And for good measure, here's a function/method you can copy and paste (tested in 5.3.3-1ubuntu9.5):
function array_md5(Array $array) {
//since we're inside a function (which uses a copied array, not
//a referenced array), you shouldn't need to copy the array
array_multisort($array);
return md5(json_encode($array));
}
md5(serialize($array));
I'm joining a very crowded party by answering, but there is an important consideration that none of the extant answers address. The value of json_encode() and serialize() both depend upon the order of elements in the array!
Here are the results of not sorting and sorting the arrays, on two arrays with identical values but added in a different order (code at bottom of post):
serialize()
1c4f1064ab79e4722f41ab5a8141b210
1ad0f2c7e690c8e3cd5c34f7c9b8573a
json_encode()
db7178ba34f9271bfca3a05c5dddf502
c9661c0852c2bd0e26ef7951b4ca9e6f
Sorted serialize()
1c4f1064ab79e4722f41ab5a8141b210
1c4f1064ab79e4722f41ab5a8141b210
Sorted json_encode()
db7178ba34f9271bfca3a05c5dddf502
db7178ba34f9271bfca3a05c5dddf502
Therefore, the two methods that I would recommend to hash an array would be:
// You will need to write your own deep_ksort(), or see
// my example below
md5( serialize(deep_ksort($array)) );
md5( json_encode(deep_ksort($array)) );
The choice of json_encode() or serialize() should be determined by testing on the type of data that you are using. By my own testing on purely textual and numerical data, if the code is not running a tight loop thousands of times then the difference is not even worth benchmarking. I personally use json_encode() for that type of data.
Here is the code used to generate the sorting test above:
$a = array();
$a['aa'] = array( 'aaa'=>'AAA', 'bbb'=>'ooo', 'qqq'=>'fff',);
$a['bb'] = array( 'aaa'=>'BBBB', 'iii'=>'dd',);
$b = array();
$b['aa'] = array( 'aaa'=>'AAA', 'qqq'=>'fff', 'bbb'=>'ooo',);
$b['bb'] = array( 'iii'=>'dd', 'aaa'=>'BBBB',);
echo " serialize()\n";
echo md5(serialize($a))."\n";
echo md5(serialize($b))."\n";
echo "\n json_encode()\n";
echo md5(json_encode($a))."\n";
echo md5(json_encode($b))."\n";
$a = deep_ksort($a);
$b = deep_ksort($b);
echo "\n Sorted serialize()\n";
echo md5(serialize($a))."\n";
echo md5(serialize($b))."\n";
echo "\n Sorted json_encode()\n";
echo md5(json_encode($a))."\n";
echo md5(json_encode($b))."\n";
My quick deep_ksort() implementation, fits this case but check it before using on your own projects:
/*
* Sort an array by keys, and additionall sort its array values by keys
*
* Does not try to sort an object, but does iterate its properties to
* sort arrays in properties
*/
function deep_ksort($input)
{
if ( !is_object($input) && !is_array($input) ) {
return $input;
}
foreach ( $input as $k=>$v ) {
if ( is_object($v) || is_array($v) ) {
$input[$k] = deep_ksort($v);
}
}
if ( is_array($input) ) {
ksort($input);
}
// Do not sort objects
return $input;
}
Answer is highly depends on data types of array values.
For big strings use:
md5(serialize($array));
For short strings and integers use:
md5(json_encode($array));
4 built-in PHP functions can transform array to string:
serialize(), json_encode(), var_export(), print_r().
Notice: json_encode() function slows down while processing associative arrays with strings as values. In this case consider to use serialize() function.
Test results for multi-dimensional array with md5-hashes (32 char) in keys and values:
Test name Repeats Result Performance
serialize 10000 0.761195 sec +0.00%
print_r 10000 1.669689 sec -119.35%
json_encode 10000 1.712214 sec -124.94%
var_export 10000 1.735023 sec -127.93%
Test result for numeric multi-dimensional array:
Test name Repeats Result Performance
json_encode 10000 1.040612 sec +0.00%
var_export 10000 1.753170 sec -68.47%
serialize 10000 1.947791 sec -87.18%
print_r 10000 9.084989 sec -773.04%
Associative array test source.
Numeric array test source.
Aside from Brock's excellent answer (+1), any decent hashing library allows you to update the hash in increments, so you should be able to update with each string sequentially, instead having to build up one giant string.
See: hash_update
md5(serialize($array));
Will work, but the hash will change depending on the order of the array (that might not matter though).
Note that serialize and json_encode act differently when it comes to numeric arrays where the keys don't start at 0, or associative arrays.
json_encode will store such arrays as an Object, so json_decode returns an Object, where unserialize will return an array with exact the same keys.
I think that this could be a good tip:
Class hasharray {
public function array_flat($in,$keys=array(),$out=array()){
foreach($in as $k => $v){
$keys[] = $k;
if(is_array($v)){
$out = $this->array_flat($v,$keys,$out);
}else{
$out[implode("/",$keys)] = $v;
}
array_pop($keys);
}
return $out;
}
public function array_hash($in){
$a = $this->array_flat($in);
ksort($a);
return md5(json_encode($a));
}
}
$h = new hasharray;
echo $h->array_hash($multi_dimensional_array);
Important note about serialize()
I don't recommend to use it as part of hashing function because it can return different result for the following examples. Check the example below:
Simple example:
$a = new \stdClass;
$a->test = 'sample';
$b = new \stdClass;
$b->one = $a;
$b->two = clone $a;
Produces
"O:8:"stdClass":2:{s:3:"one";O:8:"stdClass":1:{s:4:"test";s:6:"sample";}s:3:"two";O:8:"stdClass":1:{s:4:"test";s:6:"sample";}}"
But the following code:
<?php
$a = new \stdClass;
$a->test = 'sample';
$b = new \stdClass;
$b->one = $a;
$b->two = $a;
Output:
"O:8:"stdClass":2:{s:3:"one";O:8:"stdClass":1:{s:4:"test";s:6:"sample";}s:3:"two";r:2;}"
So instead of second object php just create link "r:2;" to the first instance. It's definitely good and correct way to serialize data, but it can lead to the issues with your hashing function.
// Convert nested arrays to a simple array
$array = array();
array_walk_recursive($input, function ($a) use (&$array) {
$array[] = $a;
});
sort($array);
$hash = md5(json_encode($array));
----
These arrays have the same hash:
$arr1 = array(0 => array(1, 2, 3), 1, 2);
$arr2 = array(0 => array(1, 3, 2), 1, 2);
I didn't see the solution so easily above so I wanted to contribute a simpler answer. For me, I was getting the same key until I used ksort (key sort):
Sorted first with Ksort, then performed sha1 on a json_encode:
ksort($array)
$hash = sha1(json_encode($array) //be mindful of UTF8
example:
$arr1 = array( 'dealer' => '100', 'direction' => 'ASC', 'dist' => '500', 'limit' => '1', 'zip' => '10601');
ksort($arr1);
$arr2 = array( 'direction' => 'ASC', 'limit' => '1', 'zip' => '10601', 'dealer' => '100', 'dist' => '5000');
ksort($arr2);
var_dump(sha1(json_encode($arr1)));
var_dump(sha1(json_encode($arr2)));
Output of altered arrays and hashes:
string(40) "502c2cbfbe62e47eb0fe96306ecb2e6c7e6d014c"
string(40) "b3319c58edadab3513832ceeb5d68bfce2fb3983"
there are several answers telling to use json_code,
but json_encode don't work fine with iso-8859-1 string, as soon as there is a special char, the string is cropped.
i would advice to use var_export :
md5(var_export($array, true))
not as slow as serialize, not as bugged as json_encode
Currently the most up-voted answer md5(serialize($array)); doesn't work well with objects.
Consider code:
$a = array(new \stdClass());
$b = array(new \stdClass());
Even though arrays are different (they contain different objects), they have same hash when using md5(serialize($array));. So your hash is useless!
To avoid that problem, you can replace objects with result of spl_object_hash() before serializing. You also should do it recursively if your array has multiple levels.
Code below also sorts arrays by keys, as dotancohen have suggested.
function replaceObjectsWithHashes(array $array)
{
foreach ($array as &$value) {
if (is_array($value)) {
$value = $this->replaceObjectsInArrayWithHashes($value);
} elseif (is_object($value)) {
$value = spl_object_hash($value);
}
}
ksort($array);
return $array;
}
Now you can use md5(serialize(replaceObjectsWithHashes($array))).
(Note that the array in PHP is value type. So replaceObjectsWithHashes function DO NOT change original array.)
in some case maybe it's better to use http_build_query to convert array to string :
md5( http_build_query( $array ) );

Categories