如何比较两个数组并显示每个键(多维数组)的差异?

时间:2015-11-29 18:33:37

标签: php arrays multidimensional-array

我想要比较两个数组:

animals1:

array(4) {
  ["1234"]=>
  array(5) {
    ["animal"]=>
    string(19) "cat"
    ["name"]=>
    string(12) "fred"
    ["food"]=>
    string(32) "milk"
  }
  ["5678"]=>
  array(5) {
    ["animal"]=>
    string(19) "dog"
    ["name"]=>
    string(12) "sam"
    ["food"]=>
    string(32) "chicken"
  }
  ["shop"]=>
  string(12) "petcenter"
}

animals2:

array(4) {
  ["1234"]=>
  array(5) {
    ["animal"]=>
    string(19) "cat"
    ["name"]=>
    string(12) "tom"
    ["food"]=>
    string(32) "juice"
  }
  ["5678"]=>
  array(5) {
    ["animal"]=>
    string(19) "dog"
    ["name"]=>
    string(12) "sam"
    ["food"]=>
    string(32) "fish"
  }
  ["shop"]=>
  string(12) "petcenter"
}

这是我的代码:

foreach ($animals1 as $k1 => $v1) {
   if (array_diff($animals2[$k1], $animals1[$k1])){
      $diff[$k1] = array_diff($animals2[$k1], $animals1[$k1]);
   }
} 
foreach ($animals2 as $k1 => $v1) {
   if (array_diff($animals1[$k1], $animals2[$k1])){
      $diff2[$k1] = array_diff($animals1[$k1], $animals2[$k1]);
   }
}
function result1($item, $key){
   echo $key."1 = ".$item;
   echo "<br>";
}
function result2($item, $key){
   echo $key."2 = ".$item;
   echo "<br>";
}
foreach ($diff as $d => $key){

    foreach ($animals1 as $p => $row) {
            if ($p == $d){
                  echo "Error for animal".$row["animal"];
                  echo "with the name:".$row["name"].".";
            }   
        }   
}
array_walk_recursive($diff, 'result1');
array_walk_recursive($diff2, 'result2');

我的结果是:

Error for animal cat with name fred.
Error for animal dog with name sam.

name1 = fred
food1 = milk
food1 = chicken

name2 = tom
food2 = juice
food2 = fish

但我需要的是:

Error for animal cat with name fred.

name1 = fred
name2 = tom

food1 = milk
food2 = juice

Error for animal dog with name sam.

food1 = chicken
food2 = fish

这意味着,首先我要显示具有特定名称的特定动物的错误。在此之后,我想显示差异。这意味着始终是animal1的值,之后是animal2的值。 我不知道如何改变我的代码是实现我希望的结果的最佳方式。

这是Standej的输出:

Error for animal cat with name fred.

name1 = fred
food1 = milk
food1 = chicken

name2 = tom
food2 = juice
food2 = fish

Error for animal dog with name sam.

name1 = fred
food1 = milk
food1 = chicken

name2 = tom
food2 = juice
food2 = fish

2 个答案:

答案 0 :(得分:1)

如果您想要重新排序的结果,请尝试重新排序代码

foreach ($animals1 as $k1 => $v1) {
   if (array_diff($animals2[$k1], $animals1[$k1])){
      $diff[$k1] = array_diff($animals2[$k1], $animals1[$k1]);
   }
} 
foreach ($animals2 as $k1 => $v1) {
   if (array_diff($animals1[$k1], $animals2[$k1])){
      $diff2[$k1] = array_diff($animals1[$k1], $animals2[$k1]);
   }
}
function result1($item, $key){
   echo $key."1 = ".$item;
   echo "<br>";
}
function result2($item, $key){
   echo $key."2 = ".$item;
   echo "<br>";
}
foreach ($diff as $d => $key){

    foreach ($animals1 as $p => $row) {
            if ($p == $d){
                  echo "Error for animal".$row["animal"];
                  echo "with the name:".$row["name"].".";
// Put your functions inside loop where you printing errors
                  array_walk_recursive($diff, 'result1');
                  array_walk_recursive($diff2, 'result2');
// End of change
            }   
        }   
}

希望它能运作

答案 1 :(得分:0)

使用array_diff的问题在于它只比较值而不是键,因此如果一只猫的名字等于另一只猫的食物,你可能无法检测到差异,而副反之亦然。

使用array_diff_assoc进行比较是一种改进。

然而,代码会遗漏一些差异,例如当第一只动物丢失钥匙时,例如没有food$diff数组不会有这种差异,并且由于代码迭代$diff,如果所有其余的都相等,相应的动物将不会包含在输出中。

原始代码还假定animalname键始终存在。

以下是一些代码,即使两边都缺少某些密钥也应该有效:

function outputDiff($animals1, $animals2) {
    foreach($animals1 as $key => $animal1) {
        // skip animals that only exist in one of the two arrays
        if (!is_array($animal1) || !isset($animals2[$key])) continue;
        $animal2 = $animals2[$key];
        if (!is_array($animal2)) continue;
        // add "animal" and "name" keys to first animal when they are missing
        $animal1 = array_merge(array("animal"=>"(unknown)","name"=>"(unknown)"),
                     $animal1);
        // collect the keys that either animal has:
        $properties = array_unique(array_merge(
                        array_keys($animal1), array_keys($animal2)));
        $equal = true;
        foreach ($properties as $property) {
            // get values from both sides, default to '(unknown)'
            $value1 = isset($animal1[$property]) ? $animal1[$property] : '(unknown)';
            $value2 = isset($animal2[$property]) ? $animal2[$property] : '(unknown)';
            if ($value1 !== $value2) {
                if ($equal) { 
                    // display header
                    echo "<h4>Error for animal {$animal1['animal']}" .
                              "with name {$animal1['name']}</h4>";
                    $equal = false;
                }
                // display detail
                echo "<p>{$property}1 = $value1<br>"; 
                echo "{$property}2 = $value2</p>";
            }
        }   
    }
}

// Set-up test data
$animals1 = array(
  "1234"=>array(
    "animal"=>"cat",
     "name"=>"fred",
    "food"=>"milk"
  ),
  "5678"=>array(
    "animal"=>"dog",
    "name"=>"sam",
    "food"=>"chicken"
  ),
  "8888"=>array(
    "animal"=>"cow",
    "name"=>"freddy",
    "food"=>"grass"
  ),
  "shop"=>"petcenter"
);
$animals2 = array(
  "1234"=>array(
    "animal"=>"cat",
    "name"=>"tom",
    "food"=>"juice"
  ),
  "5678"=>array(
    "animal"=>"dog",
    "name"=>"sam",
    "food"=>"fish"
  ),
  "shop"=>"petcenter"
);

// Perform test
outputDiff($animals1, $animals2);

此代码会输出html个标签(如果他们打扰你,请删除它们)。以上的输出是:

  

名为fred的动物猫的错误

     

name1 = fred

     

name2 = tom

     食物1 =牛奶

     食物2 =果汁

     

名为山姆的动物狗的错误

     

food1 = chicken

     食物2 =鱼