按顺序比较PHP中数组的最有效方法?

时间:2013-06-27 21:39:26

标签: php arrays compare phpunit

在PHP中使用这两个数组:

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

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

在顺序方面比较两个数组的最有效/最短/最干净的方法是什么:

  1. 显示它们是否相等(真/假)?
  2. 显示差异(例如PHPUnit)?
  3. 理想情况下,在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'
     )
    

    更新 - 解决方案

    只有当所有元素都相同时,才会生成一种diff,只是顺序不同。 PHPUnit测试:

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

3 个答案:

答案 0 :(得分:3)

您可以使用===运算符

$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 :(得分:0)

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

每个阵列只有两个迭代器,并且在一个循环中同时踩到它们并比较键+值对几乎可以完成所需的一切:

$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 :(得分:-3)

您需要array_diff_assoc(),它会比较值AND键。 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"
}