问题
Take these two arrays in PHP:
$array1 = [
2 => 'Search',
1 => 'Front-End / GUI'
];
$array2 = [
1 => 'Front-End / GUI',
2 => 'Search'
];
Most of the array comparison functions do not care about order. Doing an array_diff
will result in an empty array.
What's the most efficient / shortest / cleanest way to compare two arrays with regard to order and:
- show whether or not they are equal (true / false)?
- show the difference (such as for PHPUnit)?
Running $this->assertEquals( $array1, $array2 );
in PHPUnit ideally should yield something like:
Failed asserting that two arrays are equal.
--- Expected
+++ Actual
@@ @@
Array (
- 2 => 'Search'
- 1 => 'Front-End / GUI'
+ 1 => 'Front-End / GUI'
+ 2 => 'Search'
)
Update - Solution
This generates a sort-of diff only if all elements are same, just in different order. PHPUnit Tests:
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;
}
回答1:
You can just use the ===
operator
$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);
returns
boolean true
boolean false
then use array_diff_assoc() to find the differences
while ((list($key1, $val1) = each($array)) && (list($key2, $val2) = each($array2)) ) {
if($key1 != $key2 || $val1 != $val2) echo "- $key1 - $val1 \n + $key2 - $val2";
}
Should give some output for order
Using your array this gives me
- 2 - Search + 1 - Front-End / GUI
- 1 - Front-End / GUI + 2 - Search
you can change the output to how ever you need it
回答2:
If you are looking for a solution to generate a diff like output, i think this is a place where iterator shine:
Just having two iterators for each array and stepping trough on them simultaneously in one loop and compare key + value pairs can do almost everything you need:
$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();
}
}
Will output something like:
- 2 => Search
+ 1 => Front-End / GUI
- 1 => Front-End / GUI
+ 2 => Search
This idea of course should be expanded to handle nested arrays with RecursiveArrayIterator and probably format the output better too.
回答3:
You want array_diff_assoc(), which compares values AND keys. array_diff() considers only values.
followup: Works fine here:
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"
}
来源:https://stackoverflow.com/questions/17353683/most-efficient-way-to-compare-arrays-in-php-by-order