0

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.';
}
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
user1032531
  • 24,767
  • 68
  • 217
  • 387

5 Answers5

0

Simple code is:

$arr2;
$arr1;

$eq = true;
if (count($arr1) == count($arr2)) {
    foreach ($arr1 as $k => $v) {
        if (empty($arr2[$k]) || $arr2[$k]['Gym'] != $v['Gym'] || $arr2[$k]['Library'] != $v['Library']) {
            $eq = false;
            break;
        }
    }
} else {
    $eq = false;
}

var_dump($eq);

Update: Without fixed keys inner foreach becomes:

foreach ($arr1 as $k => $v) {
    if (empty($arr2[$k]) || array_diff_assoc($arr2[$k], $v)) {
        $eq = false;
        break;
    }
}
u_mulder
  • 54,101
  • 5
  • 48
  • 64
  • Maybe I should have said so, but the index names such as `Gym` or `Gas` cannot be hardcoded as they can be any string. – user1032531 Oct 12 '16 at 15:19
0
function arrayTwoLevelEquivalence(array $a, array $b) {
    if (count($a) !== count($b)) {
        return false;
    }
    foreach ($a as $k => $a2) {
        if (!isset($b[$k])) {
            return false;
        }
        $b2 = $b[$k];
        if (count($a2) !== count($b2)) {
            return false;
        }
        foreach ($a2 as $k2 => $v) {
            if (!array_key_exists($k2, $b2) || $b2[$k2] !== $v) {
                return false;
            }
        }
    }
    return true;
}

I decline to use array_diff_assoc() because I do not support unnecessary transient allocation of heap memory for the sake of convenience.

chaos
  • 122,029
  • 33
  • 303
  • 309
  • Definitely don't want unnecessary transient allocation of heap memory! Just curious, what does that mean? – user1032531 Oct 12 '16 at 15:34
  • @user1032531: lol. it means that `array_diff_assoc()` calculates the actual array diff as its result, meaning that result array has to be allocated in memory. Somewhere buried in the guts of PHP, that's going to be a `malloc()` on a [heap](https://en.wikipedia.org/wiki/Heap_(data_structure)). Scripting languages like PHP encourage you to think as if memory allocation were a free operation, but it's very much not (cf. "malloc churn", "heap fragmentation"), and we don't actually *care* about the array diff, just the yes/no question of equivalence. – chaos Oct 12 '16 at 19:38
0
$array1 = array("a" => "green", 'b'=>"red", 'c'=>"blue");
$array2 = array('b'=>"red", 'c'=>"blue", "a" => "green");
echo empty(array_diff_assoc($array1, $array2));

check it, hope it will fulfill your requirements. It will check if both associative array are same, whether it has same order or not.

Check it for your multidimensional array -

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)
    {
        $difference[$key] = $value;
    }
}
return !isset($difference) ? 0 : $difference;
}

I have found it from here

Jobayer
  • 1,221
  • 1
  • 14
  • 22
0

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);
apokryfos
  • 38,771
  • 9
  • 70
  • 114
  • While I only need two levels, I like your general use of a recursive function. Using `uniqid()`, however, seems a little odd. – user1032531 Oct 13 '16 at 13:54
0

If all you need to know is they match or not - without any further details:

function ksortRecursive(&$array)
{
    if (is_array($array)) {
        ksort($array);
        foreach ($array as &$arr) {
            ksortRecursive($arr);
        }
    }
}

ksortRecursive($arr1);
ksortRecursive($arr2);

if (serialize($arr1) == serialize($arr2)) {
    echo "match!";
}
Jeroen Flamman
  • 965
  • 6
  • 10