DEV Community

loading...
Cover image for Never use array_merge in a loop

Never use array_merge in a loop

chemaclass profile image Jose Maria Valera Reales Originally published at Medium Updated on ・2 min read

The spread operator to the rescue.

Flattening a one-level array

I have seen people using the array_merge function in a loop like:

$lists = [
  [1, 2],
  [3, 4],
  [5, 6],
];
$merged = [];
foreach($lists as $list) {
    $merged = array_merge($merged, $list);
}
// $merged === [1, 2, 3, 4, 5, 6];
Enter fullscreen mode Exit fullscreen mode

This is a very bad practice because it’s a (memory) performance killer!
Instead, you should use the spread operator (in PHP since 5.6!):

$lists = [
  [1, 2],
  [3, 4],
  [5, 6],
];
$merged = array_merge(...$lists);
// === [1, 2, 3, 4, 5, 6];
Enter fullscreen mode Exit fullscreen mode

Unpacking an assoc-array

What if you had an assoc-array instead like this one?

$lists = [
  'key-1' => [1, 2],
  'key-2' => [3, 4],
  'key-3' => [5, 6],
];
Enter fullscreen mode Exit fullscreen mode

In that case, you will need to unpack its values:

$merged = array_merge(...array_values($lists));
// === [1, 2, 3, 4, 5, 6];
Enter fullscreen mode Exit fullscreen mode

In Functional Programming, this is known as flatting a list.
No loops & no more performance problem.

Flatting a multilevel array

What if you wanted to flat a multilevel array like this one?

$lists = [[1], 2, [[3, 4], 5], [[[]]], [[[6]]], 7, 8, []];
Enter fullscreen mode Exit fullscreen mode

Or like this one, even with key-values?

$lists = [
    'key-1' => [
        1,
        [2],
        'key-2' => [
            3,
            [
                'key-3' => [4, 5],
            ],
        ],
    ],
    6,
    'key-4' => [7, 8],
];
Enter fullscreen mode Exit fullscreen mode

In these cases, you might want to use the internal standard library:

$merged = iterator_to_array(
    new RecursiveIteratorIterator(
        new RecursiveArrayIterator($lists)
    ),
    $use_keys = false
);
// $merged === [1, 2, 3, 4, 5, 6, 7, 8];
Enter fullscreen mode Exit fullscreen mode

Conclusion

Usually, being aware of how to flat a “2 level” array might be sufficient:

$flattenList = array_merge(...array_values($lists));
Enter fullscreen mode Exit fullscreen mode

Otherwise, the internal standard library will help you deal with it.

Alt Text

Originally published on https://chemaclass.medium.com/never-use-array-merge-in-a-loop-74917b056ff9

Discussion (4)

pic
Editor guide
Collapse
moopet profile image
Ben Sinclair

I try to avoid anything like this in PHP because I always have to look up what the difference is between array_merge and the + operator, and what order to use parameters in and which bits are going to be OO today and which bits aren't. It's just horrible.

I didn't even know there was a spread operator in PHP!

Collapse
moopet profile image
Ben Sinclair

Ah, it looks like it's been in PHP since 5.6 as an argument unpacker but only been able to unpack general arrays since 7.4.

Collapse
chemaclass profile image
Jose Maria Valera Reales Author

Well, you can use it for versions <7.4 as:

$merged = array_merge([], ...array_values($lists));
Enter fullscreen mode Exit fullscreen mode

Check it out: sandbox.onlinephpfunctions.com/cod...

And from 7.4, array_merge accept no arguments, therefore we can use it without the empty array as first arg:

$merged = array_merge(...array_values($lists));
Enter fullscreen mode Exit fullscreen mode
Collapse
suckup_de profile image
Lars Moelleken

If you use PhpStorm, then you can use the "Php Inspections ​(EA Extended)" plugin, this will check array functions in loops. :)

github.com/kalessil/phpinspections...