Php 递归数组_diff()?

Php 递归数组_diff()?,php,arrays,recursion,diff,Php,Arrays,Recursion,Diff,我正在寻找一些工具来给我两个数组的递归差异。我设想的是一个具有两种颜色编码树结构的网页。在每个树上,绿色表示两个数组中匹配的数组部分,红色表示两个数组中不匹配的部分。类似于dBug的输出 我有一些代码,它为我提供了一个嵌套数组来填充报表。我正在开发一种新方法,它应该更快,但我需要测试值和结构,以确保它提供与旧方法相同的输出 有什么我可以用的吗?还是我需要写这个?还是有其他方法可以实现我的目标?的评论中实现了一个这样的功能 该实现一次只处理两个数组,但我认为这并不存在问题。如果一次需要3个或更多阵

我正在寻找一些工具来给我两个数组的递归差异。我设想的是一个具有两种颜色编码树结构的网页。在每个树上,绿色表示两个数组中匹配的数组部分,红色表示两个数组中不匹配的部分。类似于dBug的输出

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


有什么我可以用的吗?还是我需要写这个?还是有其他方法可以实现我的目标?

的评论中实现了一个这样的功能


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

接受的答案接近正确,但它并没有真正正确地模拟数组

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

  • array\u diff
    具有一种特定行为,即如果第二个数组中的值仍在第二个数组中,它不会为第二个数组中完全缺失的数组键生成结果。如果您有两个数组
    $first=['foo'=>2,'moo'=>2]
    $second=['foo'=>2]
    ,使用接受答案的函数,输出将是
    ['moo'=>2]
    。如果通过
    array\u diff
    运行相同的数组,它将生成一个空数组。这是因为如果缺少数组键,上述函数的final
    else
    语句会将其添加到diff中,但这不是
    array\u diff
    的预期行为。这两个数组也是如此:
    $first=['foo'=>1]
    $second=[1]
    <代码>数组_diff将生成一个空数组

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

  • 以下函数与此类似,但其作用更接近于您所期望的
    array_diff
    的工作方式(也适用于不那么愚蠢的变量名):

    请尝试以下代码:

    function arrayDiffRecursive($firstArray, $secondArray, $reverseKey = false)
    {
        $oldKey = 'old';
        $newKey = 'new';
        if ($reverseKey) {
            $oldKey = 'new';
            $newKey = 'old';
        }
        $difference = [];
        foreach ($firstArray as $firstKey => $firstValue) {
            if (is_array($firstValue)) {
                if (!array_key_exists($firstKey, $secondArray) || !is_array($secondArray[$firstKey])) {
                    $difference[$oldKey][$firstKey] = $firstValue;
                    $difference[$newKey][$firstKey] = '';
                } else {
                    $newDiff = arrayDiffRecursive($firstValue, $secondArray[$firstKey], $reverseKey);
                    if (!empty($newDiff)) {
                        $difference[$oldKey][$firstKey] = $newDiff[$oldKey];
                        $difference[$newKey][$firstKey] = $newDiff[$newKey];
                    }
                }
            } else {
                if (!array_key_exists($firstKey, $secondArray) || $secondArray[$firstKey] != $firstValue) {
                    $difference[$oldKey][$firstKey] = $firstValue;
                    $difference[$newKey][$firstKey] = $secondArray[$firstKey];
                }
            }
        }
        return $difference;
    }
    
    $differences = array_replace_recursive(
        arrayDiffRecursive($firstArray, $secondArray),
        arrayDiffRecursive($secondArray, $firstArray, true)
    );
    var_dump($differences);
    
    示例:

    $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'
        )
    );
    
    array_diff_assoc_recursive($a,$b);
    
    Array
    (
        [product_a] => Array
            (
                [color] => Red
                [serial] => Array
                    (
                        [2] => 3
                    )    
            )    
    )
    
    输出:

    $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'
        )
    );
    
    array_diff_assoc_recursive($a,$b);
    
    Array
    (
        [product_a] => Array
            (
                [color] => Red
                [serial] => Array
                    (
                        [2] => 3
                    )    
            )    
    )
    
    by的答案很有效,只是需要在线更改:

    $difference[$newKey][$firstKey] = $secondArray[$firstKey];
    
    与:

    或者,如果您使用的是Laravel,则:

    $difference[$newKey][$firstKey] = array_get($secondArray, $firstKey);
    
    否则,将出现如下错误

    PHP错误:未定义索引:某些\u键


    当$secondArray中存在some_键而$firstArray中不存在时

    只是为了暂时测试这些输出,还是为了长期使用?这是一个测试,一个简单的
    wdiff
    over
    var\u导出
    输出应该会起作用……在嵌套结构中,如果一个元素是一个6的数组,而另一个是一个3的数组,那么它会跳起来吗?因为在输出中,比如说从第0-30行,它将是相同的,从最后回到第36行,它将是相同的。只有那些中间线会有所不同——3对6。如果wdiff看到这一点,它会被绊倒吗?输出不会很好地分成键/值对,但它会在进一步匹配之前和之后努力匹配行,而且,如果我只是分散检查,它会这样做。只要用一个简单的例子,看看它是否适合你的目的。另一种方法是递归函数,也不难,但需要更多的工作。只是一个想法:如果你需要一些非常快速的东西,你可以先用json_encode将其转换为字符串进行测试,比较两个字符串,如果有差异,然后进行递归检查。@Zend_Sklave,因为mhitza的答案对你有用,你也许应该把它标记为真正响应了你的请求…@JonL。我认为他必须是这个问题的作者,才能做到这一点:)这个函数返回许多根本没有改变的数据。我看不出这有什么用。此外,如果你真的想得到两个数组之间的差异,你需要运行这个函数两次,不仅要找到什么是数组1的一部分而不是数组2的一部分,还要找到什么是数组2的一部分而不是数组1的一部分。对某些人来说可能是显而易见的。。。但不是对其他人(像我一开始;)@CommaToast您能提供一个示例,说明它何时返回未更改的数据吗?对于我的两个测试,它只返回差异。你能解释一下结果有什么不同吗?对于我的测试,我得到了完全相同的结果。Thanks@JeffPuckettII对不起,我没有给你一个很好的解释。我已经更新了答案,解释了接受的答案与
    数组_diff
    的区别。刚刚在上检查了简单示例,它对简单数组的工作(行为)与预期(编辑)相同。但是递归并不像它应该的那样工作:(如果我们有值作为对象的关联数组,它就不起作用。例如,
    $a=[“foo”=>(object)[“p1”=>1,“p2”=>2],“moo”=>(object)[“p3”=>3]
    $b=[“foo”=>(object)[“p4”=>4]
    。有时考虑[1,2]和[2,1]不同并不是一个需要的愿望。数组不是元素顺序不重要的集合。PHP的数组可以表示很多东西。区分关联数组(键为任何类型)和常规数组(键为整数)并不容易。常规数组
    [1,2]
    被认为与数组
    [2,1]不同
    。这就是为什么我们有向数组的开头或结尾添加元素的函数,而不仅仅是向数组添加元素的函数(
    $difference[$newKey][$firstKey] = array_key_exists($firstKey, $secondArray) ? $secondArray[$firstKey] : null;
    
    $difference[$newKey][$firstKey] = array_get($secondArray, $firstKey);