69

How to merge n number of array in php. I mean how can I do the job like :
array_merge(from : $result[0], to : $result[count($result)-1])
OR
array_merge_recursive(from: $result[0], to : $result[count($result) -1])


Where $result is an array with multiple arrays inside it like this :

$result = Array(
0 => array(),//associative array
1 => array(),//associative array
2 => array(),//associative array
3 => array()//associative array
)

My Result is :

$result = Array(
    0 => Array(
        "name" => "Name",
        "events" => 1,
        "types" => 2
    ),
    1 => Array(
        "name" => "Name",
        "events" => 1,
        "types" => 3
    ),
    2 => Array(
        "name" => "Name",
        "events" => 1,
        "types" => 4
    ),
    3 => Array(
        "name" => "Name",
        "events" => 2,
        "types" => 2
    ),
    4 => Array(
        "name" => "Name",
        "events" => 3,
        "types" => 2
    )
)

And what I need is

$result = Array(
"name" => "name",
"events" => array(1,2,3),
"types" => array(2,3,4)
)
Lekhnath
  • 4,532
  • 6
  • 36
  • 62
  • There should be no difference. `array_merge()` + `unset()` (if needed). – BlitZ Jun 11 '13 at 09:55
  • 5
    Instead of a pseudo-code function signature, please describe the data you *have* and the result you *expect*. – deceze Jun 11 '13 at 09:55
  • I agree with deceze, this question needs a proper [mcve]. This page _could_ receive more/better answers and _could_ be use to close future duplicates -- if this question was actually completed. Right now I find this question to be Unclear. – mickmackusa Jun 26 '20 at 00:31
  • It doesn't look like ANY of the answers are grouping on the name column and generating subarrays from the remaining columns. I suggest re-closing this messy page to be a signpost for [Group row data within a 2d array based on a single column and push unique data into respective subarrays](https://stackoverflow.com/q/23109569/2943403) if this page is not outright deleted. – mickmackusa Jan 19 '23 at 08:23

4 Answers4

201

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.

complex857
  • 20,425
  • 6
  • 51
  • 54
  • @complex857 , In my case I have two arrays inside an array[ array{array1, array2}], these arrays have same parameters but I need array{[0]=>content of array1, [1]=>content of array2}. What modifications should I do in that case? – Nikita Dhiman Feb 15 '17 at 09:22
  • @NikitaDhiman, I don't think i can follow exactly what you need, but from here It seems you'll have to iterate over with `foreach` and build up the structure you want by "hand". Feels like you just have an extra array around the result you want. – complex857 Feb 15 '17 at 12:50
  • @complex857 , yes that's exactly the case...an extra array. More of like an array which has the result have two arrays inside it containing the same kind of data. The data within has to be merged – Nikita Dhiman Feb 15 '17 at 13:00
  • @NikitaDhiman in this case, if you know the key you can do `$result = $source[0]` where the `0` is the key you'll have or if you don't know the hey, you can use [`reset()`](http://php.net/manual/en/function.reset.php) to grab the first element of the array (regardless the key) like this: `$result = reset($source)` – complex857 Feb 15 '17 at 13:03
  • very good answer but please note that `$merged = array_merge(...$result);` won't work with array with string keys – Robert Trzebiński Nov 16 '18 at 16:58
  • 6
    Note that this does not actually produce the result desired in the question…!? – deceze Dec 03 '18 at 13:47
4

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
)
Community
  • 1
  • 1
Friedrich
  • 1,292
  • 1
  • 18
  • 26
4

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
)
amurrell
  • 2,383
  • 22
  • 26
0

Try this

$result = array_merge($array1, $array2);

Or, instead of array_merge, you can use the + op which performs a union:

$array2 + array_fill_keys($array1, '');
Jayram
  • 18,820
  • 6
  • 51
  • 68
  • But I need something like this : array_merge($arr_1, $arr_2, ..., $arr_n) because the `$result` variable may contain n number of associative arrays. Any Suggestion Please. – Lekhnath Jun 11 '13 at 09:59