PHP - How to merge arrays inside array PHP - How to merge arrays inside array php php

PHP - How to merge arrays inside array


array_merge can take variable number of arguments, so with a little call_user_func_array trickery you can pass your $result array to it:

$merged = call_user_func_array('array_merge', $result);

This basically run like if you would have typed:

$merged = array_merge($result[0], $result[1], .... $result[n]);

Update:

Now with 5.6, we have the ... operator to unpack arrays to arguments, so you can:

$merged = array_merge(...$result);

And have the same results. *

* The same results as long you have integer keys in the unpacked array, otherwise you'll get an E_RECOVERABLE_ERROR : type 4096 -- Cannot unpack array with string keys error.


If you would like to:

  • check that each param going into array_merge is actually an array
  • specify a particular property within one of the arrays to merge by

You can use this function:

function mergeArrayofArrays($array, $property = null){    return array_reduce(        (array) $array, // make sure this is an array too, or array_reduce is mad.        function($carry, $item) use ($property) {            $mergeOnProperty = (!$property) ?                    $item :                    (is_array($item) ? $item[$property] : $item->$property);            return is_array($mergeOnProperty)                ? array_merge($carry, $mergeOnProperty)                : $carry;    }, array()); // start the carry with empty array}

Let's see it in action.. here's some data:

Simple structure: Pure array of arrays to merge.

$peopleByTypesSimple = [    'teachers' => [            0  => (object) ['name' => 'Ms. Jo', 'hair_color' => 'brown'],            1  => (object) ['name' => 'Mr. Bob', 'hair_color' => 'red'],    ],    'students' => [            0  => (object) ['name' => 'Joey', 'hair_color' => 'blonde'],            1  => (object) ['name' => 'Anna', 'hair_color' => 'Strawberry Blonde'],    ],    'parents' => [            0  => (object) ['name' => 'Mr. Howard', 'hair_color' => 'black'],            1  => (object) ['name' => 'Ms. Wendle', 'hair_color' => 'Auburn'],    ],];

Less simple: Array of arrays, but would like to specify the people and ignore the count.

$peopleByTypes = [    'teachers' => [        'count' => 2,        'people' => [            0  => (object) ['name' => 'Ms. Jo', 'hair_color' => 'brown'],            1  => (object) ['name' => 'Mr. Bob', 'hair_color' => 'red'],        ]    ],    'students' => [        'count' => 2,        'people' => [            0  => (object) ['name' => 'Joey', 'hair_color' => 'blonde'],            1  => (object) ['name' => 'Anna', 'hair_color' => 'Strawberry Blonde'],        ]    ],    'parents' => [        'count' => 2,        'people' => [            0  => (object) ['name' => 'Mr. Howard', 'hair_color' => 'black'],            1  => (object) ['name' => 'Ms. Wendle', 'hair_color' => 'Auburn'],        ]    ],];

Run it

$peopleSimple = mergeArrayofArrays($peopleByTypesSimple);$people = mergeArrayofArrays($peopleByTypes, 'people');

Results - Both return this:

Array(    [0] => stdClass Object        (            [name] => Ms. Jo            [hair_color] => brown        )    [1] => stdClass Object        (            [name] => Mr. Bob            [hair_color] => red        )    [2] => stdClass Object        (            [name] => Joey            [hair_color] => blonde        )    [3] => stdClass Object        (            [name] => Anna            [hair_color] => Strawberry Blonde        )    [4] => stdClass Object        (            [name] => Mr. Howard            [hair_color] => black        )    [5] => stdClass Object        (            [name] => Ms. Wendle            [hair_color] => Auburn        ))

Extra Fun: If you want to single out one property in an array or object, like "name" from an array of people objects(or associate arrays), you can use this function

function getSinglePropFromCollection($propName, $collection, $getter = true){    return (empty($collection)) ? [] : array_map(function($item) use ($propName) {        return is_array($item)             ? $item[$propName]             : ($getter)                 ? $item->{'get' . ucwords($propName)}()                : $item->{$propName}    }, $collection);}

The getter is for possibly protected/private objects.

$namesOnly = getSinglePropFromCollection('name', $peopleResults, false);

returns

Array(    [0] => Ms. Jo    [1] => Mr. Bob    [2] => Joey    [3] => Anna    [4] => Mr. Howard    [5] => Ms. Wendle)


I really liked the answer from complex857 but it didn't work for me, because I had numeric keys in my arrays that I needed to preserve.

I used the + operator to preserve the keys (as suggested in PHP array_merge with numerical keys) and used array_reduce to merge the array.

So if you want to merge arrays inside an array while preserving numerical keys you can do it as follows:

<?php$a = [    [0 => 'Test 1'],    [0 => 'Test 2', 2 => 'foo'],    [1 => 'Bar'],];    print_r(array_reduce($a, function ($carry, $item) { return $carry + $item; }, []));?>

Result:

Array(    [0] => Test 1    [2] => foo    [1] => Bar)