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])
?
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With