我正在寻找一些工具来给我一个两个数组的递归diff。我设想的是一个带有两个颜色编码树结构的网页。在每棵树上,绿色是阵列的两个阵列中匹配的部分,而红色是每个树中与另一个不匹配的部分。类似于dBug的输出
我有一些代码可以为我提供一个嵌套数组来填充报表。我正在开发一个应该更快的新方法,但我需要测试值和结构,以确保它提供与旧方法相同的输出。
我可以使用哪些东西吗?或者我需要写这个吗?或者还有另一种方法来实现我的目标吗?
答案 0 :(得分:57)
在array_diff的评论中实现了一个这样的功能。
function arrayRecursiveDiff($aArray1, $aArray2) {
$aReturn = array();
foreach ($aArray1 as $mKey => $mValue) {
if (array_key_exists($mKey, $aArray2)) {
if (is_array($mValue)) {
$aRecursiveDiff = arrayRecursiveDiff($mValue, $aArray2[$mKey]);
if (count($aRecursiveDiff)) { $aReturn[$mKey] = $aRecursiveDiff; }
} else {
if ($mValue != $aArray2[$mKey]) {
$aReturn[$mKey] = $mValue;
}
}
} else {
$aReturn[$mKey] = $mValue;
}
}
return $aReturn;
}
实现一次只处理两个数组,但我不认为这确实存在问题。如果一次需要3个或更多数组的diff,则可以按顺序运行diff。此方法也使用密钥检查并进行松散的验证。
答案 1 :(得分:9)
接受的答案接近正确,但它并没有真正模仿array_diff
。
有两个问题主要围绕密钥匹配:
array_diff
有一个特定的行为,如果第二个数组的值仍然在第二个数组中,它就不会产生第二个数组完全丢失的数组键的结果。如果您有两个数组$first = ['foo' => 2, 'moo' => 2]
和$second = ['foo' => 2]
,则使用接受的答案函数,输出将为['moo' => 2]
。如果通过array_diff
运行相同的数组,它将生成一个空数组。这是因为如果数组键丢失,上面函数的最终else
语句会将它添加到diff中,但这不是array_diff
的预期行为。这两个数组也是如此:$first = ['foo' => 1]
和$second = [1]
。 array_diff
将生成一个空数组。
如果两个数组具有相同的值但键不同,则返回的值多于预期值。如果您有两个数组$foo = [1, 2]
和$moo = [2, 1]
,则接受的答案中的函数将输出$foo
中的所有值。这是因为它在每次迭代时都进行严格的密钥匹配,它在两个数组中找到相同的密钥(数字或其他),而不是检查第二个数组中的所有其他值。
以下函数类似,但更接近于您期望array_diff
工作的方式(也使用不太愚蠢的变量名称):
function array_diff_recursive($arr1, $arr2)
{
$outputDiff = [];
foreach ($arr1 as $key => $value)
{
//if the key exists in the second array, recursively call this function
//if it is an array, otherwise check if the value is in arr2
if (array_key_exists($key, $arr2))
{
if (is_array($value))
{
$recursiveDiff = array_diff_recursive($value, $arr2[$key]);
if (count($recursiveDiff))
{
$outputDiff[$key] = $recursiveDiff;
}
}
else if (!in_array($value, $arr2))
{
$outputDiff[$key] = $value;
}
}
//if the key is not in the second array, check if the value is in
//the second array (this is a quirk of how array_diff works)
else if (!in_array($value, $arr2))
{
$outputDiff[$key] = $value;
}
}
return $outputDiff;
}
答案 2 :(得分:4)
function array_diff_assoc_recursive($array1, $array2)
{
foreach($array1 as $key => $value){
if(is_array($value)){
if(!isset($array2[$key]))
{
$difference[$key] = $value;
}
elseif(!is_array($array2[$key]))
{
$difference[$key] = $value;
}
else
{
$new_diff = array_diff_assoc_recursive($value, $array2[$key]);
if($new_diff != FALSE)
{
$difference[$key] = $new_diff;
}
}
}
elseif((!isset($array2[$key]) || $array2[$key] != $value) && !($array2[$key]===null && $value===null))
{
$difference[$key] = $value;
}
}
return !isset($difference) ? 0 : $difference;
}
示例:强>
$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
)
)
)
答案 3 :(得分:2)
试试这段代码:
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);
答案 4 :(得分:0)
Mohamad的回答很好,除了需要在线更改之外
$difference[$newKey][$firstKey] = $secondArray[$firstKey];
具有:
$difference[$newKey][$firstKey] = array_key_exists($firstKey, $secondArray) ? $secondArray[$firstKey] : null;
或者,如果您使用的是Laravel,请使用:
$difference[$newKey][$firstKey] = array_get($secondArray, $firstKey);
否则,您将收到类似错误
PHP错误:未定义索引:some_key
在$ secondArray中存在some_key但在$ firstArray中不存在