Search code examples
phparraysrecursionmultidimensional-arrayarray-difference

Find differences between two multidimensional arrays recursively with strict type checking


I have 2 arrays

  • $cpe
  • $sample

$cpe array info

array:23 [▼
  "cpe_mac" => "298639133839"
  "bandwidth_max_up" => 30000
  "bandwidth_max_down" => 50000
  "filter_icmp_inbound" => true
  "dmz_enabled" => false
  "dmz_host" => "http:\/\/ddd.com"
  "vlan_id" => 2
  "dns" => array:2 [▶]
  "xdns_mode" => 0
  "cfprofileid" => 11111
  "stub_response" => "0"
  "acl_mode" => 1
  "portal_url" => "http:\/\/portal.com"
  "fullbandwidth_max_up" => 1000000
  "fullbandwidth_max_down" => 2000000
  "fullbandwidth_guaranty_up" => 300000
  "fullbandwidth_guaranty_down" => 400000
  "account_id" => 1000
  "location_id" => 3333
  "network_count" => 3
  "group_name" => "test_group"
  "vse_id" => 20
  "firewall_enabled" => false
]

$sample array info

array:23 [▼
  "cpe_mac" => "a0a1a2a3a4a5"
  "bandwidth_max_up" => 300000
  "bandwidth_max_down" => 500000
  "filter_icmp_inbound" => true
  "dmz_enabled" => false
  "dmz_host" => "http] = \/\/ddd.com"
  "vlan_id" => 2
  "dns" => array:2 [▶]
  "xdns_mode" => 0
  "cfprofileid" => 11111
  "stub_response" => ""
  "acl_mode" => 1
  "portal_url" => "http] = \/\/portal.com"
  "fullbandwidth_max_up" => 1000000
  "fullbandwidth_max_down" => 2000000
  "fullbandwidth_guaranty_up" => 300000
  "fullbandwidth_guaranty_down" => 400000
  "account_id" => 1234
  "location_id" => 3333
  "network_count" => 3
  "group_name" => "test_group"
  "vse_id" => 20
  "firewall_enabled" => false
]

I look through them countless time with my eyes, they look the same to me except their value. Then, I compare them programmatically,

$equal = ($cpe == $sample );
dd($equal); // false

I think, it return false because their values is different. Am I right ?


How do I check if those array have the same

  • length
  • key
  • data-type

If different, how can I find out what is it exactly that make them different?


Solution

  • I'm not sure how you believe that these arrays can be equal. They're clearly not.

    For example $sample["cpe_mac"] == "a0a1a2a3a4a5" and $cpe["cpe_mac"] == "298639133839". Also $sample["bandwidth_max_up"] == 300000 and $cpe["bandwidth_max_up"] == 30000. Just by looking at the array you can immediately tell they aren't equal so there's no logical reason to believe that $cpe == $sample should ever be true.

    Also array_diff compares values as strings. What you have is a multi-dimensional array. So it is not possible to compute the differences of non-scalar elements in the array with array_diff.

    Note:

    This function only checks one dimension of a n-dimensional array. Of course you can check deeper dimensions by using array_diff($array1[0], $array2[0]);.

    Also a second note the manual elaborates...

    Note:

    Two elements are considered equal if and only if (string) $elem1 === (string) $elem2. In words: when the string representation is the same.


    To compute the the non equal elements between the two arrays you may need to iterate over them and compare one element at a time.

    Example

    $diff = [];
    
    foreach($cpe as $key => $value) {
        if (array_key_exists($key, $sample) && $sample[$key] !== $value) {
            $diff[$key] = $sample[$key];
        }
    }
    

    You could also write this as a recursive function to compute differences within n-dimensional arrays...

    function array_diff_recursive(Array $a, Array $b, Array $diff = [])
    {
        foreach($a as $k => $v) {
            if (!array_key_exists($k, $b)) {
                $diff[$k] = $v;
                continue;
            }
            if (is_array($v)) {
                $diff += array_diff_recursive($v, $b[$k], $diff);
            } else {
                if ($v !== $b[$k]) { // you could change this to == for loose comparison
                    $diff[$k] = $v;
                }
            }
        }
        return $diff;
    }