Search code examples
phpmultidimensional-arraymergegroupingstdclass

Merging and group two arrays containing objects based on one identifying column value


I have a trouble regarding merging arrays by specific scenario. Searching for similar cases gave no results here. To understand clearly what is my requirements, please look at the next example:

$array1 = [
    (object) ['call_date' => '2013-10-22 00:00:00', 'first_amount' => 10],
    (object) ['call_date' => '2013-10-23 00:00:00', 'first_amount' => 20],
];

$array2 = [
    (object) ['call_date' => '2013-10-22 00:00:00', 'second_amount' => 30],
    (object) ['call_date' => '2013-10-24 00:00:00', 'second_amount' => 40],
];

What I need as the output:

Array
(
    [0] => stdClass
        (
            [call_date] => 2013-10-22 00:00:00
            [first_amount] => 10
            [second_amount] => 30
        )

    [1] => stdClass
        (
            [call_date] => 2013-10-23 00:00:00
            [first_amount] => 20
        )

    [2] => stdClass
        (
            [call_date] => 2013-10-24 00:00:00
            [second_amount] => 40
        )
)

So as you can see merging goes by call_date. Items from the first and the second array which are under the date 2013-10-22 00:00:00 was combined, item from the second array under the date 2013-10-24 00:00:00 was appended.

Tried a lot of combinations of array_merge, array_udiff, array_merge_recursive, array_map, but nothing helped.


Solution

  • Simple scenario:

    1. change array keys
    2. merge recursive
    3. map merged elements back to object (stdClass)

    Example:

    //change key
    $workFirstArray = array_combine(
        array_map(function($object) { return $object->call_date;}, $firstArray), $firstArray
    );
    $workSecondArray = array_combine(
        array_map(function($object) { return $object->call_date;}, $secondArray), $secondArray
    );
    
    //map merged elements back to StdClass
    $result = array_map(function($element) {
            if(is_array($element)) {
                $element['call_date'] = end($element['call_date']);
                $element=(object)$element;
            }
            return $element;
        },
        array_merge_recursive($workFirstArray, $workSecondArray)
    );
    

    output:

    Array
    (
        [0] => stdClass Object
            (
                [call_date] => 2013-10-22 00:00:00
                [first_amount] => 10
                [second_amount] => 40
            )
    
        [1] => stdClass Object
            (
                [call_date] => 2013-10-23 00:00:00
                [second_amount] => 30
            )
    
        [2] => stdClass Object
            (
                [call_date] => 2013-10-24 00:00:00
                [second_amount] => 40
            )
    
    )