【问题标题】:Most efficient way to compare arrays in PHP by order?按顺序比较PHP中数组的最有效方法?
【发布时间】:2013-06-25 13:49:51
【问题描述】:

在 PHP 中取这两个数组:

$array1 = [
    2 => 'Search',
    1 => 'Front-End / GUI'
];
$array2 = [
    1 => 'Front-End / GUI',
    2 => 'Search'
];

大多数数组比较函数不关心顺序。执行array_diff 将导致一个空数组。

比较两个数组的顺序和最有效/最短/最简洁的方法是什么:

  1. 显示它们是否相等(真/假)?
  2. 显示差异(例如对于 PHPUnit)?

在 PHPUnit 中运行 $this->assertEquals( $array1, $array2 ); 理想情况下应该会产生类似的结果:

Failed asserting that two arrays are equal.
--- Expected
+++ Actual
@@ @@
 Array (
-    2 => 'Search'
-    1 => 'Front-End / GUI'
+    1 => 'Front-End / GUI'
+    2 => 'Search'
 )

更新 - 解决方案

只有当所有元素都相同,只是顺序不同时,才会产生一种差异。 PHP单元测试:

public function test...() {
    $actual = someCall();
    $expected = [...];

    // tests for same elements
    $this->assertEquals( $expected, $actual );

    // tests for same order
    $diff = $this->array_diff_order( $expected, $actual );
    $this->assertTrue( $expected === $actual, "Failed asserting that two arrays are equal order.\n--- Expected\n+++ Actual\n@@ @@\n Array(\n$diff )" );
}

private function array_diff_order( $array1, $array2 ) {
    $out = '';
    while ((list($key1, $val1) = each($array1)) && (list($key2, $val2) = each($array2)) ) {
        if($key1 != $key2 || $val1 != $val2) $out .= "-    $key1 => '$val1' \n+    $key2 => '$val2'\n";
    }
    return $out;
}

【问题讨论】:

    标签: php arrays compare phpunit


    【解决方案1】:

    您可以只使用=== 运算符

    $array = array(1 => "test", 2=> "testing");
    $array2 = array(1 => "test", 2=> "testing");
    
    var_dump($array === $array2);
    
    $array2 = array(2 => "test", 1=> "testing");
    var_dump($array === $array2);
    

    返回

    boolean true
    boolean false
    

    然后使用 array_diff_assoc() 找出差异

    while ((list($key1, $val1) = each($array)) && (list($key2, $val2) = each($array2)) ) {
        if($key1 != $key2 || $val1 != $val2) echo "- $key1 - $val1 \n + $key2 - $val2";
    }
    

    应该为订单提供一些输出

    使用你的数组这给了我

    • 2 - 搜索 + 1 - 前端/GUI
    • 1 - 前端/GUI + 2 - 搜索

    您可以根据需要更改输出

    【讨论】:

    • 这回答了问题 1。有人回答问题 2 吗?
    • “然后使用 array_diff_assoc() 来找出差异”这不是回答问题 2 吗?
    • 正如我提到的,array_diff_assoc() 不检查订单。 Marc 的第二个数组与我的不同。
    • 它们是一样的,你可以通过 var_dump 确认为什么顺序很重要?
    • 在这种情况下,顺序确实很重要 :) 这就是为什么这个问题与 SE 上的其他一千个问题不同。
    【解决方案2】:

    如果您正在寻找生成类似输出的差异的解决方案,我认为这是迭代器大放异彩的地方:

    只需为每个数组设置两个迭代器,并在一个循环中同时遍历它们并比较键 + 值对即可完成几乎所有您需要的操作:

    $array1 = [
        2 => 'Search',
        1 => 'Front-End / GUI'
    ];
    $array2 = [
        1 => 'Front-End / GUI',
        2 => 'Search'
    ];
    
    $it0 = new ArrayIterator($array1);
    $it1 = new ArrayIterator($array2);
    
    while ($it0->valid() || $it1->valid()) {
        if ($it0->valid() && $it1->valid()) {
            if ($it0->key() != $it1->key() || $it0->current() != $it1->current()) {
                print "- ".$it0->key().' => '.$it0->current()."\n";
                print "+ ".$it1->key().' => '.$it1->current()."\n";
            }
            $it0->next();
            $it1->next();
        } elseif ($it0->valid()) {
            print "- ".$it0->key().' => '.$it0->current()."\n";
            $it0->next();
        } elseif ($it1->valid()) {
            print "+ ".$it1->key().' => '.$it1->current()."\n";
            $it1->next();
        }
    }
    

    会输出如下内容:

    - 2 => Search
    + 1 => Front-End / GUI
    - 1 => Front-End / GUI
    + 2 => Search
    

    这个想法当然应该扩展为处理带有RecursiveArrayIterator 的嵌套数组,并可能更好地格式化输出。

    【讨论】:

    • 这确实可以回答问题 2。最好寻找更简单、更清晰、更符合断言的东西。
    • 我也可以使用foreach,但如果可能的话,我正在寻找一些干净的东西。
    • 我认为 foreach 仅当您的两个数组长度相同时才有效,或者您必须在循环之外以某种方式处理非重叠部分。我认为你也总是可以隐藏函数背后的逻辑,创建差异很难(-:
    【解决方案3】:

    你想要array_diff_assoc(),它比较值和键。 array_diff() 只考虑值。


    跟进:在这里工作正常:

    php > $arr1 = array(2 => 'Search', 1 => 'Front');
    php > $arr2 = array(1 => 'Search', 2 => 'Front');
    php > var_dump(array_diff_assoc($arr1, $arr2));
    array(2) {
      [2]=>
      string(6) "Search"
      [1]=>
      string(5) "Front"
    }
    

    【讨论】:

    • array_diff_assoc() 也返回一个空数组
    • 你的第二个数组和我的不同
    • @joe:PHP 不考虑数组的内部排序差异。这完全取决于解释器中的内部内存指针的状态,这些指针 NOT 在脚本级别公开。如果键和/或值是相同的,那么对于 array_diff/array_diff_assoc 来说也是相同的。
    猜你喜欢
    • 1970-01-01
    • 2014-06-20
    • 2020-05-24
    • 2016-04-13
    • 1970-01-01
    • 2021-10-16
    • 1970-01-01
    • 2014-05-15
    • 1970-01-01
    相关资源
    最近更新 更多