26

How can I compare multidimensional arrays in php? Is there a simple way?

NullUserException
  • 83,810
  • 28
  • 209
  • 234
Kevin
  • 489
  • 2
  • 5
  • 15

6 Answers6

48

The simplest way I know:

$a == $b;

Note that you can also use the ===. The difference between them is:

  1. With Double equals ==, order is important:

    $a = array(0 => 'a', 1 => 'b');
    $b = array(1 => 'b', 0 => 'a');
    var_dump($a == $b);  // true
    var_dump($a === $b); // false
    
  2. With Triple equals ===, types matter:

    $a = array(0, 1);
    $b = array('0', '1');
    var_dump($a == $b);  // true
    var_dump($a === $b); // false
    

Reference: Array operators

Akshay
  • 700
  • 9
  • 23
NullUserException
  • 83,810
  • 28
  • 209
  • 234
13

Another way to do it is to serialize() both of the arrays and compare the strings.

http://php.net/manual/en/function.serialize.php

Geoffrey Hale
  • 10,597
  • 5
  • 44
  • 45
user151841
  • 17,377
  • 29
  • 109
  • 171
11

This function will do it all for you.

You can use it to truly compare any 2 arrays of same or totally different structures.

It will return:

Values in array1 not in array2 (more)

Values in array2 not in array1 (less)

Values in array1 and in array2 but different (diff)

//results for array1 (when it is in more, it is in array1 and not in array2. same for less)
function compare_multi_Arrays($array1, $array2){
    $result = array("more"=>array(),"less"=>array(),"diff"=>array());
    foreach($array1 as $k => $v) {
      if(is_array($v) && isset($array2[$k]) && is_array($array2[$k])){
        $sub_result = compare_multi_Arrays($v, $array2[$k]);
        //merge results
        foreach(array_keys($sub_result) as $key){
          if(!empty($sub_result[$key])){
            $result[$key] = array_merge_recursive($result[$key],array($k => $sub_result[$key]));
          }
        }
      }else{
        if(isset($array2[$k])){
          if($v !== $array2[$k]){
            $result["diff"][$k] = array("from"=>$v,"to"=>$array2[$k]);
          }
        }else{
          $result["more"][$k] = $v;
        }
      }
    }
    foreach($array2 as $k => $v) {
        if(!isset($array1[$k])){
            $result["less"][$k] = $v;
        }
    }
    return $result;
}
Kareem
  • 5,068
  • 44
  • 38
  • I've tested your function and got as 'more' a value under an existing key. Yo must use `array_key_exists($k, $array2[$k])` instead the test `isset($array2[$k])` because isset tests the key exists and **has a not null value**. – quevedo Feb 23 '21 at 03:22
  • I have a misstype . I must wrote `array_key_exists($k, $array2)` – quevedo Feb 23 '21 at 14:11
  • I use this function in production and never had an issue. If you find a way of improving it please let me know. Thanks @quevedo – Kareem Feb 24 '21 at 03:18
  • You mention that your function will work with "2 arrays of same or totally different structures." I have two arrays and I have tried every conversion I am aware of but none are working in your function. It prints the expected three arrays (more/less/diff) but they are empty. Here is a partial example of my array format: Array1 ([{"id":"100000565","position":"Cost Containment Analyst","area":"Warehouse (Domestic US)","ro":"","span":"0",) and Array2([{"id":"100000567","position":"Global Logistics Specialist","area":"Shipping/Receiving","ro":1,"span":). – Neil_Tinkerer Oct 20 '21 at 19:11
  • 1
    Works perfectly comparing multidimensional arrays! Well done @Kareem ! – gtamborero Jan 27 '22 at 08:43
2
function multi_diff($arr1,$arr2){
  $result = array();
  foreach ($arr1 as $k=>$v){
    if(!isset($arr2[$k])){
      $result[$k] = $v;
    } else {
      if(is_array($v) && is_array($arr2[$k])){
        $diff = multi_diff($v, $arr2[$k]);
        if(!empty($diff))
          $result[$k] = $diff;
      }
    }
  }
  return $result;
}

//example:

var_dump(multi_diff(

array(
  "A"=>array(
    "A1"=>array('A1-0','A1-1','A1-2','A1-3'),
    "A2"=>array('A2-0','A2-1','A2-2','A2-3'),
    "A3"=>array('A3-0','A3-1','A3-2','A3-3')
  ),
  "B"=>array(
    "B1"=>array('B1-0','B1-1','B1-2','B1-3'),
    "B2"=>array('B2-0','B2-1','B2-2','B2-3'),
    "B3"=>array('B3-0','B3-1','B3-2','B3-3')
  ),
  "C"=>array(
    "C1"=>array('C1-0','C1-1','C1-2','C1-3'),
    "C2"=>array('C2-0','C2-1','C2-2','C2-3'),
    "C3"=>array('C3-0','C3-1','C3-2','C3-3')
  ),
  "D"=>array(
    "D1"=>array('D1-0','D1-1','D1-2','D1-3'),
    "D2"=>array('D2-0','D2-1','D2-2','D2-3'),
    "D3"=>array('D3-0','D3-1','D3-2','D3-3')
  )
),

array(
  "A"=>array(
    "A1"=>array('A1-0','A1-1','A1-2','A1-3'),
    "A2"=>array('A2-0','A2-1','A2-2','A2-3'),
    "A3"=>array('A3-0','A3-1','A3-2')
  ),
  "B"=>array(
    "B1"=>array('B1-0','B1-2','B1-3'),
    "B2"=>array('B2-0','B2-1','B2-2','B2-3'),
    "B3"=>array('B3-0','B3-1','B3-3')
  ),
  "C"=>array(
    "C1"=>array('C1-0','C1-1','C1-2','C1-3'),
    "C3"=>array('C3-0','C3-1')
  ),
  "D"=>array(
    "D1"=>array('D1-0','D1-1','D1-2','D1-3'),
    "D2"=>array('D2-0','D2-1','D2-2','D2-3'),
    "D3"=>array('D3-0','D3-1','D3-2','D3-3')
  )
)

));
  • 1
    Some explanation of logic would make a nicer answer :) – Amicable Mar 19 '14 at 16:52
  • This will not handle X by X it is only one level deep – Mike Q Oct 31 '16 at 17:12
  • Also won't handle if the second array has more elements than the first. Identical issue to the function this was copied from – Robbie Dec 19 '16 at 00:18
  • You don't need to call the function inside itself you should call array_intersect($v, $arr2[$k]); inside the function it will compare the array and return a single array to you. – Mudit Gulgulia Aug 17 '20 at 10:01
0
$difference = array();
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($value, $array2[$key]);
            if($new_diff != FALSE)
            {
                $difference[$key] = $new_diff;
            }
        }
    }
    elseif(!isset($array2[$key]) || $array2[$key] != $value)
    {
        $difference[$key] = $value;
    }
}
0

To compare array's structure, You should use identity operator.

if($arrayA === $arrayB) {
    ...
}
Fedir RYKHTIK
  • 9,844
  • 6
  • 58
  • 68
  • The only difference(s) between this and my answer is that instead of using `==` for the elements in the array, it will use `===`, and with `===` it checks the order of key value pairs. From what I understood from the question, the OP wants `==`, **NOT** `===`. And I also put a link on my answer if the OP is interested in that. – NullUserException Sep 12 '11 at 14:21
  • 1
    One symbol here makes a lot of difference. – Fedir RYKHTIK Sep 12 '11 at 14:24
  • So you are telling me that given `$a = array(1 => 'a', 0 => 'b'); $b = array(0 => 'b', 1 => 'a');`, the OP wants something that would return false? Interesting. – NullUserException Sep 12 '11 at 14:26
  • Author wants "to compare if they (arrays) have exactly the same content and the same structure". Check the PHP example : $b = array(1 => "banana", "0" => "apple"); var_dump($a == $b); // bool(true) var_dump($a === $b); // bool(false) – Fedir RYKHTIK Sep 12 '11 at 14:35
  • Hy Guys, thanks for help. But you only tell me the way to compare one dimensional arrays. But how about compare two or three dimensional arrays? Like Example :`a = array(1 => 'a', 0 => array(1 => 'b')); ` and `$b = array(1 => "banana", "0" => array(0 => 'apple'));` ? – Kevin Sep 15 '11 at 07:07