为啥 array_diff() 给出数组到字符串的转换错误?

Posted

技术标签:

【中文标题】为啥 array_diff() 给出数组到字符串的转换错误?【英文标题】:Why array_diff() gives Array to string conversion error?为什么 array_diff() 给出数组到字符串的转换错误? 【发布时间】:2013-11-18 18:46:31 【问题描述】:

以下行出现数组到字符串转换错误:

$diff = array_diff($stockist, $arr);

这里,$arr 是从 JSON 文件解码的数组。使用is_array() 函数,我能够验证这两个参数都是数组。有人能指出我的问题吗

$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 说的没什么不同。问题是数组到字符串的转换,而不是相反。问题是这些数组包含 @viakondratiuk 是的,它是多维的。但不是 array_diff() 只评估第一级 @user2963765 此函数仅检查 n 维数组的一维。当然你可以使用array_diff($array1[0], $array2[0]);来检查更深的维度。 您可以使用recursive array_diff。看看这个gist.github.com/jondlm/7709e54f84a3f1e1b67b,它解决了我的问题...... 【参考方案1】:

据此:

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

您的其中一个数组是多维的。

array_diff 只检查 n 维数组的一维。当然你可以使用array_diff($array1[0], $array2[0]);来检查更深的维度

【讨论】:

对我来说似乎是一个错误。 “数组到字符串的转换”消息充其量是误导性的。 快到 2020 年了,仍然存在的信息误导了我 现在是 2020 年,我同样对这个错误感到困惑。 现在是 2021 年,我讨厌一切。 现在是 2022 年,我仍然讨厌这一切【参考方案2】:

是的,严格的答案是因为“您的数组之一是多维的。”

另一个有用的注释可能是 - 取决于您进一步解析实际差异的需要 - 考虑首先测试您的数组:

$diff = strcmp(json_encode($stockist), json_encode($arr));

$diff = strspn(json_encode($stockist) ^ json_encode($arr), "\0");

$diff = xdiff_string_diff(json_encode($stockist), json_encode($arr));

所有这些选项都会比较整个数组树,而不仅仅是顶层。

【讨论】:

$diff = strcmp(json_encode($stockist), json_encode($arr));不起作用,当两者之间存在差异时总是返回 0【参考方案3】:

由于array_diff 只能处理一维,您可以:

将您的多维数组转换为一维,例如作者:

flattening a multidimensional array,例如:

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,例如:

$results = array_diff(array_map('serialize',$a2), array_map('serialize',$a1)); 

使用自定义recursive array_diff-like function,

【讨论】:

多维数组的展平是错误的。当接近第一个嵌套数组时,函数会忘记原始 $arr 中的所有其他值。 完美!与最受欢迎的答案相反,反序列化起作用。只需要做 $results = array_map('unserialize', $results);后记阅读它 第二个例子正是我要找的,谢谢!!【参考方案4】:

根据函数的 PHP 文档

注意: 当且仅当 (string) $elem1 === (string) $elem2 时,才认为两个元素相等。换句话说:当字符串表示相同时。

更多信息请参考http://php.net/manual/en/function.array-diff.php

【讨论】:

我只需要比较键。所以我使用了array_diff_key()。但它返回一个空数组。 如果它返回一个空数组,这意味着两个数组具有相同的一组键。【参考方案5】:

你可以在array_diff() documentation看到:

两个元素被认为相等当且仅当 (string) $elem1 === (字符串)$elem2。换句话说:当字符串表示是 一样。

所以看起来你不能将此函数用于多维数组,或者实际上任何不能转换为字符串的值。这是因为该函数会将值转换为 string 以进行比较。

您可以编写自己的函数来递归检查数组是否存在差异 - 事实上,以下内容来自上面链接的文档的 cmets。

你可以看到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; 

【讨论】:

令人吃惊的是,PHP 语言作者认为不编写函数的递归版本就可以了。并将数组保留为字符串转换错误,而不是让错误说“不支持多维数组”【参考方案6】:

今天在为 PHP 7.3 从 5.3 进行平台升级时遇到了这个问题……因为我要存储这个值以供以后使用,所以我想确保我没有以“部分”结束序列化数组,可能会破坏下游。

感谢 kenorb 让我走上正确的道路(我赞成你的回答)。以下对我很有效。

代码:

$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);

输出:

Array
(
    [foo] => bar
    [bar] => Array
        (
            [test] => test
        )

)

【讨论】:

与kenorb提供的答案有何不同? 它包括使用 array_map('unserialize', $diff) 以便 $diff 数组的格式保持多维而没有任何序列化。我在 cmets 中看到了它,但是那个文本很小而且很容易被忽略。 稍微扩展你的答案:function diffMultiDim($dataLeft, $dataRight) return array_map('unserialize', array_diff(array_map('serialize', $dataLeft), array_map('serialize', $数据右))); 【参考方案7】:

这是我对类似问题的解决方案。我想比较两个关联数组并返回更改后的值,但其中一些元素是数组。所以如果我使用

array_diff_assoc

,它给了我“数组到字符串错误”。我的函数还将比较数组元素,如果有差异,它将返回数组元素。它仍在进行中,尚未进行广泛测试。 例如:

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);

如果你运行 ::test 它将返回:

array(2) 
    ["status"]=>
    int(2)
    ["different"]=>
    array(2) 
    ["old"]=>
    int(5)
    ["new"]=>
    int(9)
  

【讨论】:

【参考方案8】:

我也遇到了同样的错误,发现下面的 php 错误报告:

https://bugs.php.net/bug.php?id=60198

比较多个数组中元素的一些array_*函数 通过 (string)$elem1 === (string)$elem2 这样做。

如果 $elem1 或 $elem2 是一个数组,那么数组到字符串通知是 扔了。

可以抛出 this 的两个函数示例是 array_intersect() 和 array_diff()。

如果不期望这些函数与其他数组一起使用数组 作为值,这应该在文档页面上提及。

该报告描述了为什么 php 在比较多维数组时会抛出错误。

【讨论】:

【参考方案9】:

我的解决方案呢:

$diff = strcmp(serialize($arr1), serialize($arr2))

【讨论】:

你的解决方案只返回差异,但我需要返回孔级别和差异的关键【参考方案10】:

我们收到强制转换为字符串警告,因为 array_diff 在比较之前将元素转换为字符串...并且我们已经传递了整数,关键是添加一个包装器对象,因为对象可以转换为字符串,然后比较时完成后,我们将它们返回到整数,如下所示

或者-

您可以使用库https://github.com/voku/Arrayy#diffarray-array-static 它的 has 方法称为 diff() 也可以比较纯整数和其他数据类型

【讨论】:

以上是关于为啥 array_diff() 给出数组到字符串的转换错误?的主要内容,如果未能解决你的问题,请参考以下文章

深思 PHP 数组遍历的差异(array_diff 的实现)

php array_intersect() 和 array_diff() 函数

使用 diff 和 intersect 的 php 数组比较似乎没有给出我需要的结果

array_diff应用

带有实例或自定义回调函数的 PHP array_diff?

php函数 array_diff