Why array_diff() gives Array to string conversion error?
PhpArraysMultidimensional ArrayArray DifferencePhp Problem Overview
I get array to string conversion error for the following line:
$diff = array_diff($stockist, $arr);
Here, $arr
is an array decoded from a JSON file. Using the is_array()
function I was able to verify that both parameters are arrays. Can someone point me the problem
$stockist = array();
while (!feof($file_handle)) {
$line_of_text = fgetcsv($file_handle);
$query = "SELECT * FROM reorderchart WHERE medicine = '"
. trim($line_of_text[3])
. "' ORDER BY medicine";
$result = mysql_query($query);
if (trim($line_of_text[2]) - trim($line_of_text[1]) <= 0) {
while ($row = mysql_fetch_array($result)) {
$file = "results.json";
$arr = json_decode(file_get_contents($file),true);
$pharmacy = trim($row['Medicine']);
if (isset($stockist[$pharmacy])) {
$medicine = $stockist[$pharmacy];
$medicine[] = trim($row['Stockist']);
$stockist[$pharmacy] = $medicine;
} else {
$medicine = array();
$medicine[] = trim($row['Stockist']);
$stockist[$pharmacy] = $medicine;
}
}
}
}
$diff = array();
$diff = array_diff_assoc($stockist,$arr);
ksort($diff);
foreach ($diff as $key => $value) {
echo "<table align='center' border='1'>";
echo "<tr><td align = 'center'> <font color = 'blue'> $key</td></tr>";
foreach($value as $key1 => $value1) {
echo "<tr><td align ='center'>$value1</td></tr><br>";
}
echo "</table>";
}
Php Solutions
Solution 1 - Php
According to it:
php -r 'array_diff(array("a" => array("b" => 4)), array(1));'
PHP Notice: Array to string conversion in Command line code on line 1
PHP Stack trace:
PHP 1. {main}() Command line code:0
PHP 2. array_diff() Command line code:1
One of your arrays is multidimensional.
array_diff
only checks one dimension of a n-dimensional array. Of course you can check deeper dimensions by using array_diff($array1[0], $array2[0]);
Solution 2 - Php
Yes, the strict answer is because "One of your arrays is multidimensional."
Another useful note might be - depending on your needs of further parsing the actual differences - consider first testing your arrays with:
$diff = strcmp(json_encode($stockist), json_encode($arr));
or
$diff = strspn(json_encode($stockist) ^ json_encode($arr), "\0");
or
$diff = xdiff_string_diff(json_encode($stockist), json_encode($arr));
All these options will compare the entire array tree, not just the top level.
Solution 3 - Php
Since array_diff
can only deals with one dimension, you can either:
-
convert your multi-dimentional array into one dimension, e.g. by:
-
flattening a multidimensional array, e.g.:
while ($arr) { list($key, $value) = each($arr); is_array($value) ? $arr = $value : $out[$key] = $value; unset($arr[$key]); } // Now $out is flatten version of $arr.
-
serializing the array, e.g.:
$results = array_diff(array_map('serialize',$a2), array_map('serialize',$a1));
-
-
use custom recursive
array_diff
-like function,
Solution 4 - Php
According to PHP documentation for the function
> Note: Two elements are considered equal if and only if (string) $elem1 === (string) $elem2. In words: when the string representation is the same.
For more information refer to http://php.net/manual/en/function.array-diff.php
Solution 5 - Php
You can see in the array_diff() documentation that:
> Two elements are considered equal if and only if (string) $elem1 === > (string) $elem2. In other words: when the string representation is the > same.
So it looks like you can't use this function with multi dimensional array, or in fact any value that cannot be converted to a string. This is because the function will cast values to a string
to do the comparison.
You can write your own function to recursively check arrays for a difference - in fact the following is from the comments of the docs linked above.
You can see the comment here.
function arrayRecursiveDiff($aArray1, $aArray2) {
$aReturn = array();
foreach ($aArray1 as $mKey => $mValue) {
if (array_key_exists($mKey, $aArray2)) {
if (is_array($mValue)) {
$aRecursiveDiff = arrayRecursiveDiff($mValue, $aArray2[$mKey]);
if (count($aRecursiveDiff)) { $aReturn[$mKey] = $aRecursiveDiff; }
} else {
if ($mValue != $aArray2[$mKey]) {
$aReturn[$mKey] = $mValue;
}
}
} else {
$aReturn[$mKey] = $mValue;
}
}
return $aReturn;
}
Solution 6 - Php
Came across this one while working on a platform upgrade for PHP 7.3 from 5.3 today... Since I'm storing this value for use later on, I wanted to be sure I didn't wind up with a 'partially' serialized array that may break things downstream.
Thanks kenorb for getting me onto the right path (I upvoted ur answer). The following is working nicely for me.
Code:
$a1 = [
'foo' => 'bar',
'bar' => [
'test' => 'test'
],
'foobar' => 'fizzbuzz'
];
$a2 = [
'foobar' => 'fizzbuzz',
'herp' => [
'derp' => 'herpderp'
]
];
$diff = array_diff(array_map('serialize', $a1), array_map('serialize', $a2));
$multidimensional_diff = array_map('unserialize', $diff);
print_r($multidimensional_diff);
Output:
Array
(
[foo] => bar
[bar] => Array
(
[test] => test
)
)
Solution 7 - Php
This is my solution for a similar problem. I want to compare two associative arrays and return the changed values, but some of the elements are arrays. So if I use
array_diff_assoc
, it gives me "Array to string error". My function will also compare the elements which are arrays and if there's a difference, it will return the array element. It is still a work in progress and not tested extensively. For example:
public static $example1 = [
'id' => 1,
'status' => 2,
'elements' => ['test', 'example'],
'different' => ['old' => 5, 'new' => 9]
];
public static $example2 = [
'id' => 1,
'status' => 3,
'elements' => ['test', 'example'],
'different' => ['old' => 5, 'new' => 8]
];
public static function test(){
die(var_dump(self::udiffAssoc(self::$example1, self::$example2)));
}
public static function udiffAssoc(array $array1, array $array2)
{
$checkDiff = function ($a, $b) use (&$checkDiff) {
if (is_array($a) && is_array($b)) {
return array_udiff_assoc($a, $b, $checkDiff);
} elseif (is_array($a)) {
return 1;
} elseif (is_array($b)) {
return -1;
} elseif ($a === $b) {
return 0;
} else {
return $a > $b ? 1 : -1;
}
};
return array_udiff_assoc($array1, $array2, $checkDiff);
}
if you run ::test it will return:
array(2) {
["status"]=>
int(2)
["different"]=>
array(2) {
["old"]=>
int(5)
["new"]=>
int(9)
}
}
Solution 8 - Php
I've got the same error and found the following bug report for php:
https://bugs.php.net/bug.php?id=60198
> Some of the array_* functions that compare elements in multiple arrays > do so by (string)$elem1 === (string)$elem2. > > If $elem1 or $elem2 is an array, then the array to string notice is > thrown. > > Two examples of functions that can throw this are array_intersect() > and array_diff(). > > If these functions are not expected to take arrays with other arrays > as values, this should be mentioned on the documentation pages.
That report describes, why php throws an error on comparing a multi-dimensional array.
Solution 9 - Php
What about my solution:
$diff = strcmp(serialize($arr1), serialize($arr2))
Solution 10 - Php
We're getting cast to string warning because array_diff converts the elements to string before comparing... and we've passed ints, the key is to add a wrapper object since objects can be casted to string, then when comparison is done we're returning them back to ints as below
Or-
Your can just use a library https://github.com/voku/Arrayy#diffarray-array-static its have method called diff() can compare straight integer and other data types as well