phparraysmultidimensional-arrayfilterarray-difference

How to use array_udiff() to filter out whole rows which are identical between two 2d arrays?


I have two multidimensional arrays that both look something like this:

Array
(
    [0] => Array (
         'id' => 3,
         'other' => 'some string',
         'timestamp' => 2000-01-01 00:00:00
    ),

    [1] => Array (
         'id' => 6,
         'other' => 'another string',
         'timestamp' => 1835-01-01 00:00:00
    )
)

I'm trying to find a way to figure out which elements show up in one array ($b), but not the other ($a) and if there are any elements with changed values. If $a is:

Array
(
    [0] => Array (
         'id' => 3,
         'other' => 'some string',
         'timestamp' => 2000-01-01 00:00:00
    )
)

and $b is:

Array
(
    [0] => Array (
         'id' => 3,
         'other' => 'some string',
         'timestamp' => 2000-01-01 12:12:12
    ),

    [1] => Array (
         'id' => 4,
         'other' => 'some string',
         'timestamp' => 1900-01-01 01:12:23
    )
)

Then the function should return:

Array
(
    [0] => Array (
         'id' => 3,
         'other' => 'some string',
         'timestamp' => 2000-01-01 12:12:12
    ),

    [1] => Array (
         'id' => 4,
         'other' => 'some string',
         'timestamp' => 1900-01-01 01:12:23
    )
)

because the element with id = 3 has been changed (the timestamp field) and the element with id = 4 is new and doesn't appear in the other array.

I've been trying to do this with array_udiff, but I still don't know how it works (it seems to sort both arrays first, but then how does it do comparison?). Is array_udiff the proper method or should I write a custom function?


Solution

  • You can use array_udiff and define your own comparison callback. I assume that both arrays has exactly the same structure.

    You can define your own callback function as follow:

    function comparison(Array $a, Array $b): int {
        if ($a['id']==$b['id'] && $a['other']==$b['other'] && $a['timestamp']==$b['timestamp']){
            return 0
        }else{
            return -1
        }
    }
    

    The callback function must return a negative integer if first argument is less than the second; a positive number if it's bigger; or 0 if it's equal. Then, you can return any number different to 0 to indicate that the arguments are different and 0 if they are the equal.

    Finally, you should call array_udiffas follow:

    array_udiff($a, $b, 'comparison')
    

    And you will get a list of the elements of $a which are not, or are different in $b.

    Note that if you want to compare 2 array when one of then has more elements than the other, you should pass as first argument the array with the new elements.