Search code examples
phparraysmultidimensional-arrayarray-merge

How to compare and later merge two multidimensional arrays


I am trying to merge two multidimensional arrays in following way (example arrays are only examples, real ones are very long and have thousands of items):

$array_a:

[0] => Array
    (
        [date] => 2018-02-25 15:12
        [request] => 0
    )
[1] => Array
    (
        [date] => 2018-02-25 15:13
        [request] => 0
    )
[2] => Array
    (
        [date] => 2018-02-25 15:14
        [request] => 0
    )
[3] => Array
    (
        [date] => 2018-02-25 15:15
        [request] => 0
    )

$array_b:

[0] => Array
    (
        [date] => 2018-02-25 15:12
        [request] => 11
    )
[1] => Array
    (
        [date] => 2018-02-25 15:13
        [request] => 5
    )
[2] => Array
    (
        [date] => 2018-02-25 15:15
        [request] => 2
    )

Needed result:

[0] => Array
    (
        [date] => 2018-02-25 15:12
        [request] => 11
    )
[1] => Array
    (
        [date] => 2018-02-25 15:13
        [request] => 5
    )
[2] => Array
    (
        [date] => 2018-02-25 15:14
        [request] => 0
    )
[3] => Array
    (
        [date] => 2018-02-25 15:15
        [request] => 2
    )

Any? Thanks.


Solution

  • I can give you the result, however I don't know the logic that goes in the callback body.

    $array_c = array_values(array_reduce(array_merge($a, $b), function($carry, $item) {
        $carry[$item['date']] = $item;
        return $carry;
    }, []));
    

    https://3v4l.org/fSVoj

    What I'm doing is combining the arrays (they're all subset'd, so no inherent conflicts), then I go through and "reduce down" to an array key > value pairing, the key being the date/time, the value being the set. This gives the effect of coalescing each date/time to the same key in that array. The callback in this case simply "remembers" the last date/time block encountered, hence the "not sure what's needed" question.

    Lastly, I get a version of the array with the date/times replaced with indexes (array_values()). This is also interesting, because sorting by date would be fairly easy if the array_values() call were moved to later.

    This gives:

    array(4) {
      [0]=>
      array(2) {
        ["date"]=>
        string(16) "2018-02-25 15:12"
        ["request"]=>
        int(11)
      }
      [1]=>
      array(2) {
        ["date"]=>
        string(16) "2018-02-25 15:13"
        ["request"]=>
        int(5)
      }
      [2]=>
      array(2) {
        ["date"]=>
        string(16) "2018-02-25 15:14"
        ["request"]=>
        int(0)
      }
      [3]=>
      array(2) {
        ["date"]=>
        string(16) "2018-02-25 15:15"
        ["request"]=>
        int(2)
      }
    }
    

    Different things can be done, like only keep the first, or add each request (they're all zero in the first array). The mechanism should be the same though.