递归array_diff()?

use*_*841 33 php arrays recursion diff

我正在寻找一些工具来给我一个两个数组的递归diff.我设想的是一个带有两个颜色编码树结构的网页.在每棵树上,绿色是阵列的两个阵列中匹配的部分,而红色是每个树中与另一个不匹配的部分.类似于dBug的输出

我有一些代码,它给我一个嵌套数组来填充报告.我正在开发一个应该更快的新方法,但我需要测试值和结构,以确保它提供与旧方法相同的输出.

我可以使用哪些东西吗?或者我需要写这个吗?或者还有另一种方法来实现我的目标吗?

mhi*_*tza 61

array_diff的注释中实现了一个这样的函数.

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;
} 
Run Code Online (Sandbox Code Playgroud)

该实现一次只处理两个数组,但我不认为这确实存在问题.如果一次需要3个或更多数组的diff,则可以按顺序运行diff.此方法也使用密钥检查并进行松散的验证.

  • @JonL.我认为他必须成为问题的作者才能做到这一点:) (6认同)
  • 此函数返回许多根本没有更改的数据.我不明白这是多么有用. (5认同)
  • 此外,如果你真的想要得到两个数组之间的区别,你需要运行这个函数**两次**不仅要找到数组1的一部分而不是数组2的一部分,而且还要找到数组2的一部分但是不是阵列1的一部分.对某些人来说可能是显而易见的......但不是对其他人(一开始就像我一样;)) (2认同)

tre*_*ace 11

接受的答案接近正确,但它并没有真正模拟array_diff正确.

有两个问题主要围绕密钥匹配:

  1. array_diff具有特定的行为,如果第二个数组的仍在第二个数组中,则它不会产生第二个数组完全丢失的数组键的结果.如果你有两个数组,$first = ['foo' => 2, 'moo' => 2]$second = ['foo' => 2]使用接受的答案函数输出['moo' => 2].如果你运行相同的数组array_diff,它将产生一个空数组.这是因为else如果数组键丢失,上面函数的final 语句会将它添加到diff中,但这不是预期的行为array_diff.这两个数组也是如此:$first = ['foo' => 1]$second = [1].array_diff将生成一个空数组.

  2. 如果两个数组具有相同的值但键不同,则返回的值多于预期值.如果你有两个数组$foo = [1, 2]$moo = [2, 1],功能从接受的答案将输出的所有值从$foo.这是因为它在每次迭代时都进行严格的密钥匹配,它在两个数组中找到相同的密钥(数字或其他),而不是检查第二个数组中的所有其他值.

以下函数类似,但更接近于您期望array_diff的工作方式(也使用不太愚蠢的变量名称):

function array_diff_recursive($arr1, $arr2)
{
    $outputDiff = [];

    foreach ($arr1 as $key => $value)
    {
        //if the key exists in the second array, recursively call this function 
        //if it is an array, otherwise check if the value is in arr2
        if (array_key_exists($key, $arr2))
        {
            if (is_array($value))
            {
                $recursiveDiff = array_diff_recursive($value, $arr2[$key]);

                if (count($recursiveDiff))
                {
                    $outputDiff[$key] = $recursiveDiff;
                }
            }
            else if (!in_array($value, $arr2))
            {
                $outputDiff[$key] = $value;
            }
        }
        //if the key is not in the second array, check if the value is in 
        //the second array (this is a quirk of how array_diff works)
        else if (!in_array($value, $arr2))
        {
            $outputDiff[$key] = $value;
        }
    }

    return $outputDiff;
}
Run Code Online (Sandbox Code Playgroud)

  • @JeffPuckettII对不起,我没有给出很好的解释。我已经更新了答案,以解释所接受的答案与`array_diff`有何不同。 (2认同)

JRo*_*ryB 5

function array_diff_assoc_recursive($array1, $array2)
{
    foreach($array1 as $key => $value){

        if(is_array($value)){
            if(!isset($array2[$key]))
            {
                $difference[$key] = $value;
            }
            elseif(!is_array($array2[$key]))
            {
                $difference[$key] = $value;
            }
            else
            {
                $new_diff = array_diff_assoc_recursive($value, $array2[$key]);
                if($new_diff != FALSE)
                {
                    $difference[$key] = $new_diff;
                }
            }
        }
        elseif((!isset($array2[$key]) || $array2[$key] != $value) && !($array2[$key]===null && $value===null))
        {
            $difference[$key] = $value;
        }
    }
    return !isset($difference) ? 0 : $difference;
}
Run Code Online (Sandbox Code Playgroud)

例子:

$a = array(
    "product_a" => array(
        'description'=>'Product A',
        'color'=>'Red',
        'quantity'=>'5',
        'serial'=>array(1,2,3)
    ),
    "product_b" => array(
        'description'=>'Product B'
    )
);

$b = array(
    "product_a" => array(
        'description'=>'Product A',
        'color'=>'Blue',
        'quantity'=>'5',
        'serial'=>array(1,2,5)
    ),
    "product_b" => array(
        'description'=>'Product B'
    )
);
Run Code Online (Sandbox Code Playgroud)

输出:

array_diff_assoc_recursive($a,$b);

Array
(
    [product_a] => Array
        (
            [color] => Red
            [serial] => Array
                (
                    [2] => 3
                )    
        )    
)
Run Code Online (Sandbox Code Playgroud)