note 89635 modified in function.array-diff-assoc by thiago
| From: | thiago@php.net | Date: | Thu, 30 Jul 2009 12:12:03 +0000 |
| Subject: | note 89635 modified in function.array-diff-assoc by thiago | ||
| References: | 1 | Groups: | php.notes |
| Request: | Send a blank email to php-notes+get-158913@lists.php.net to get a copy of this message | ||
I've worked on array_diff_assoc_recursive() mentioned by chinello at gmail dot com and I think
it might be worth mentioning here. I wrote a dozen test cases and it seems to be holding up pretty
well.
<?php
// dwarven Differences:
// * Replaced isset() with array_key_exists() to account for keys with null contents
// 55 dot php at imars dot com Differences:
// Key differences:
// * Removed redundant test;
// * Returns false bool on exact match (not zero integer);
// * Use type-precise comparison "!==" instead of loose "!=";
// * Detect when $array2 contains extraneous elements;
// * Returns "before" and "after" instead of only "before" arrays on
mismatch.
function array_compare($array1, $array2) {
$diff = false;
// Left-to-right
foreach ($array1 as $key => $value) {
if (!array_key_exists($key,$array2)) {
$diff[0][$key] = $value;
} elseif (is_array($value)) {
if (!is_array($array2[$key])) {
$diff[0][$key] = $value;
$diff[1][$key] = $array2[$key];
} else {
$new = array_compare($value, $array2[$key]);
if ($new !== false) {
if (isset($new[0])) $diff[0][$key] = $new[0];
if (isset($new[1])) $diff[1][$key] = $new[1];
};
};
} elseif ($array2[$key] !== $value) {
$diff[0][$key] = $value;
$diff[1][$key] = $array2[$key];
};
};
// Right-to-left
foreach ($array2 as $key => $value) {
if (!array_key_exists($key,$array1)) {
$diff[1][$key] = $value;
};
// No direct comparsion because matching keys were compared in the
// left-to-right loop earlier, recursively.
};
return $diff;
};
?>
Note that to catch small type differences, you need to use var_dump() rather than print_r(). For
example:
<?php
first = Array( 'first' => 'second', 'third' =>
'fourth',
'fifth' => Array( 'oui' => 'yes', 'non' =>
'no' ),
'sixth' => Array( 3, 4, 2, 1 )
);
$second = Array( 'first' => 'second', 'third' =>
'fourth',
'fifth' => Array( 'oui' => 'yes', 'non' =>
'no' ),
'sixth' => Array( 3, 4, '2', 1 )
);
$diff = array_compare($first, $second);
if ($diff === false) echo "MATCH\n";
else var_dump($diff);
?>
The above would immediately show that element "sixth", index 2, is int(2) in $first but
string(1)"2" in $second. As per the original function, order for associative arrays does
not matter, and of course it does with lists.
[EDIT: Credits to php dot notes at dwarven dot co dot uk]
--was--
I've worked on array_diff_assoc_recursive() mentioned by chinello at gmail dot com and I think
it might be worth mentioning here. I wrote a dozen test cases and it seems to be holding up pretty
well.
<?php
// Key differences:
// * Removed redundant test;
// * Returns false bool on exact match (not zero integer);
// * Use type-precise comparison "!==" instead of loose "!=";
// * Detect when $array2 contains extraneous elements;
// * Returns "before" and "after" instead of only "before" arrays on
mismatch.
function array_compare($array1, $array2) {
$diff = false;
// Left-to-right
foreach ($array1 as $key => $value) {
if (!isset($array2[$key])) {
$diff[0][$key] = $value;
} elseif (is_array($value)) {
if (!is_array($array2[$key])) {
$diff[0][$key] = $value;
$diff[1][$key] = $array2[$key];
} else {
$new = array_compare($value, $array2[$key]);
if ($new !== false) {
if (isset($new[0])) $diff[0][$key] = $new[0];
if (isset($new[1])) $diff[1][$key] = $new[1];
};
};
} elseif ($array2[$key] !== $value) {
$diff[0][$key] = $value;
$diff[1][$key] = $array2[$key];
};
};
// Right-to-left
foreach ($array2 as $key => $value) {
if (!isset($array1[$key])) {
$diff[1][$key] = $value;
};
// No direct comparsion because matching keys were compared in the
// left-to-right loop earlier, recursively.
};
return $diff;
};
?>
Note that to catch small type differences, you need to use var_dump() rather than print_r(). For
example:
<?php
first = Array( 'first' => 'second', 'third' =>
'fourth',
'fifth' => Array( 'oui' => 'yes', 'non' =>
'no' ),
'sixth' => Array( 3, 4, 2, 1 )
);
$second = Array( 'first' => 'second', 'third' =>
'fourth',
'fifth' => Array( 'oui' => 'yes', 'non' =>
'no' ),
'sixth' => Array( 3, 4, '2', 1 )
);
$diff = array_compare($first, $second);
if ($diff === false) echo "MATCH\n";
else var_dump($diff);
?>
The above would immediately show that element "sixth", index 2, is int(2) in $first but
string(1)"2" in $second. As per the original function, order for associative arrays does
not matter, and of course it does with lists.
http://php.net/manual/en/function.array-diff-assoc.php