Search code examples
phparraysmultidimensional-arraycomparisonassociative-array

Check if associative multi-dimensional arrays are equal regardless of order of keys in either level


The two arrays are considered equal since they have the same 1st dimension indexes (Electric, Gas, Water) the same 2nd dimension indexes (Gym, Library), and the same values for each intersect. The second level values will always be scalar (not arrays or objects). Order doesn't matter.

How can PHP verify that they are equal based on the above definition of equality?

$array1 = [
    'Electric' => ['Gym' => 24, 'Library' => 25],
    'Gas' => ['Gym' => 13, 'Library' => null],
    'Water' => ['Gym' => null, 'Library' => null]
];

$array2 = [
    'Gas' => ['Library' => null, 'Gym' => 13],
    'Electric' => ['Gym' => 24, 'Library' => 25],
    'Water' => ['Library' => null, 'Gym' => null]
];

My attempt is as follows...

if (count($arr1) != count($arr2) || array_diff($arr1, $arr2) !== array_diff($arr2, $arr1)) {
    $error = 'Values do not match.';
}

Solution

  • Here's a recursive comparison function

    function CompareRecursive($array1, $array2, &$mismatches) {
        foreach ($array1 as $key => $value) {
            if (!isset($array2[$key])) { 
                $mismatches[$key] = [ $value ];
                continue;
            } 
    
            $value2 = $array2[$key];  
            if (!is_array($value) || !is_array($value2)) {                
                if ($value != $value2) {
                    $mismatches[$key] = [
                        $value, $value2
                    ];
                }
            } else {
                $mismatches_internal = [];
                CompareRecursive($value, $value2, $mismatches_internal);
                if (!empty($mismatches_internal)) {
                    $mismatches[$key] = $mismatches_internal;
                }
            } 
        }
        return empty($mismatches);
    }
    

    As an added bonus this keeps track of mismatched entries too, there's a drawback when using this method that it won't work if $array2 has extra elements that $array1 doesn't but you can resolve this by doing:

    $isEqual = CompareRecursive($array1,$array2) && CompareRecursive($array2,$array1);