Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What exactly is concat + apply doing to flatten an array?

Tags:

javascript

I've basically memorized this [].concat.apply([], a) to flatten an array that isn't deeply nested but I don't entirely understand how it works. For instance, where does apply comes into this?

Is it more efficient than arr.reduce((x,y) => [...x,...y]) ?

like image 806
Curly Avatar asked Dec 06 '22 10:12

Curly


1 Answers

There are a couple of aspects to this:

concat flattens (to one level) arrays you pass into it, including only their elements in the resulting array:

console.log([1, 2, 3].concat(4, 5, [6, 7, 8]));

Notice how the array at the end was flattened.

The apply is Function.prototype.apply: You can use it to call a function specifying what this should be and providing the arguments for the function as an array. That last bit is critical: The array's elements are passed to concat as discrete arguments, and if any of those are arrays, concat extracts their content. So

let a = [[1, 2, 3], 4, 5, [6, 7, 8]];
a = [].concat.apply([], a);
//  ^^--- (1)       ^^--- (2)

...calls concat with this being array (2) above, passing in the arguments [1, 2, 3], 4, 5, and [6, 7, 8]. (Array (1) is only used to get concat, then thrown away.)

[].concat.apply([], a) is a bit wasteful (it creates two throw-away arrays, both of the ones indicated above), though it's not likely to matter; really it should be `Array.prototype.concat.apply([], although that still creates and throws away one of them. (Obviously, you'd tuck that away in a reusable function so you don't have to type that out every time.)

But in modern JavaScript you may want to use flat instead, with a polyfill if necessary:

console.log(
  [
    [1, 2, 3],
    4, 5,
    [6, 7, 8]
  ].flat()
);

The above works on up-to-date versions of Chrome, Firefox, and Safari, but again you can use a polyfill to use it on other browsers.

Note that flat optionally does recursive flattening. By default it does just one level (like concat), but if you specify a depth argument, you can go deeper (you can use Infinity to handle all levels).

like image 171
T.J. Crowder Avatar answered Dec 25 '22 05:12

T.J. Crowder