2

How to list the keys of two multidimensional arrays for which the value ares different ?

Example of given array.

$array1 = [
  'a' => 'Barbapapa',
  'b' => 'Barbouille',
  'c' => [
    'foo' => 'Barbamama'
  ],
  'd' => 'Barbabelle'
];
$array2 =[
  'a' => 'Barbapapa',
  'b' => 'Barbotine',
  'c' => [
    'foo' => 'Barbamama',
    'bar' => 'Barbidur'
  ]
]

Returned array (any other format is fine):

['b', 'c.bar', 'd']

So, I tried this (from this post):

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;
}
>>> arrayRecursiveDiff($array1, $array2)
=> [
     "b" => "Barbouille",
     "d" => "Barbabelle",
   ]

But I'm not getting the missing c.bar.

DevonDahon
  • 7,460
  • 6
  • 69
  • 114
  • 2
    Have you attempted anything? If so, please share your effort and explain where and how it fails to do what you need. – El_Vanja Mar 02 '21 at 15:57
  • @El_Vanja I first tried `array_intersect()` but it doesn't work with multidimensional arrays – DevonDahon Mar 02 '21 at 16:00
  • 1
    You'll have to do some looping/recursion, but https://www.php.net/manual/en/function.array-diff-assoc.php – AbraCadaver Mar 02 '21 at 16:02
  • 1
    Intersection is the opposite operation of what you're trying to do. What you seem to need is a recursive version of the array difference. – El_Vanja Mar 02 '21 at 16:03
  • @El_Vanja Indeed, I have updated my post with an example of what I tried. – DevonDahon Mar 02 '21 at 16:25
  • 1
    The issue here is that `array_diff` only searches for elements present in the first array that are not present in the second one. What you need is a comparison that goes both ways, meaning you need to run it twice, with the order of the parameters changed and merge that. – El_Vanja Mar 02 '21 at 18:57
  • Wrote two functions for you in an answer below, tested and it works :) – Oliver M Grech Mar 03 '21 at 22:19

1 Answers1

2

Add these two functions

function array_merge_xor($a, $b) {
    $result = array_merge(array_diff($a, $b), array_diff($b, $a));
    return $result;
}

function array_flatten($array) {
    $return = array();
    foreach ($array as $key => $value) {
        if (is_array($value)){
            foreach($value as $subKey => $subVal){
                $valueNew[$key.'.'.$subKey] = $value[$subKey];
            }
            
            $return = array_merge($return, array_flatten($valueNew));
        } else {
            $return[$key] = $value;
        }
    }

    return $return;
}

And then call your arrays like this....

$x = array_merge_xor(array_flatten($array1), array_flatten($array2));

print_r($x);
Oliver M Grech
  • 3,071
  • 1
  • 21
  • 36