399

What is the most efficient way to concatenate N arrays of objects in JavaScript?

The arrays are mutable, and the result can be stored in one of the input arrays.

1

24 Answers 24

466

If you're concatenating more than two arrays, concat() is the way to go for convenience and likely performance.

var a = [1, 2], b = ["x", "y"], c = [true, false];
var d = a.concat(b, c);
console.log(d); // [1, 2, "x", "y", true, false];

For concatenating just two arrays, the fact that push accepts multiple arguments consisting of elements to add to the array can be used instead to add elements from one array to the end of another without producing a new array. With slice() it can also be used instead of concat() but there appears to be no performance advantage from doing this.

var a = [1, 2], b = ["x", "y"];
a.push.apply(a, b);
console.log(a); // [1, 2, "x", "y"];

In ECMAScript 2015 and later, this can be reduced even further to

a.push(...b)

However, it seems that for large arrays (of the order of 100,000 members or more), the technique passing an array of elements to push (either using apply() or the ECMAScript 2015 spread operator) can fail. For such arrays, using a loop is a better approach. See https://stackoverflow.com/a/17368101/96100 for details.

Sign up to request clarification or add additional context in comments.

13 Comments

I believe your test may have an error: the a.concat(b) test case seems to be needlessly making a copy of the array a then throwing it away.
@ninjagecko: You're right. I updated it: jsperf.com/concatperftest/6. For the particular case of creating a new array that concatenates two existing arrays, it appears concat() is generally faster. For the case of concatenating an array onto an existing array in place, push() is the way to go. I updated my answer.
I can attest that extending a single array with several new arrays using the push.apply method confers a huge performance advantage (~100x) over the simple concat call. I'm dealing with very long lists of short lists of integers, in v8/node.js.
An even more concise way is a.push(...b);
@dinvlad: True, but only in ES6 environments. I've added a note to my answer.
|
203
[].concat.apply([], [array1, array2, ...])

proof of efficiency: http://jsperf.com/multi-array-concat/7

Tim Supinie mentions in the comments that this may cause the interpreter to exceed the call stack size. This is perhaps dependent on the js engine, but I've also gotten "Maximum call stack size exceeded" on Chrome at least. Test case: [].concat.apply([], Array(300000).fill().map(_=>[1,2,3])). (I've also gotten the same error using the currently accepted answer, so one is anticipating such use cases or building a library for others, special testing may be necessary no matter which solution you choose.)

15 Comments

@c69: it seems about as efficient as the chosen answer of repeatedly .push(#,#,...,#), on Chrome at least. jsperf.com/multi-array-concat The chosen answer by Tim Down may also have an error in it. This link is a performance comparison of joining multiple arrays as the question asked (not just 2); multiple possible lengths are tested.
IMO this is the most effective way to "merge" n arrays, well done
This answer is particularly useful when N is not known ahead of time such as when you have an array of arrays of arbitrary length and you want them all concatenated.
With ES6 and spread operators it get's even simpler: [].concat(...[array1, array2, ...]) Well, the second three dots are a bit unfortunate. The first three is the spread operator developer.mozilla.org/en/docs/Web/JavaScript/Reference/…
Just FYI, this method can fill up the call stack if N is very large. I tried a case where N is ~225K and ran into this issue.
|
74

New Answer

For array of multiple arrays and ES6, use

arr.flat();

For example:

const arr = [[1, 2, 3], [4, 5, 6], [7, 8 ,9]];
const newArr = arr.flat();
// output: [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]

This will work with node > 11 and modern browsers.


Old Answer

(leaving it here just in case it's needed for old node versions):

For array of multiple arrays and ES6, use

Array.prototype.concat(...arr);

For example:

const arr = [[1, 2, 3], [4, 5, 6], [7, 8 ,9]];
const newArr = Array.prototype.concat(...arr);
// output: [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]

3 Comments

In addition you can remove duplicate elements by using newArr = Array.from(new Set(newArr));.
Why in typescript does this become any[]? The typing is there - weird.
This is actually pretty horribly inefficient at larger array volumes. jsperf.com/flatten-array-203948 [].concat.apply([], ...arr) performs vastly better at large volumes.
51

For people using ES2015 (ES6)

You can now use the Spread Syntax to concatenate arrays:

const arr1 = [0, 1, 2],
      arr2 = [3, 4, 5];

const result1 = [...arr1, ...arr2]; // -> [0, 1, 2, 3, 4, 5]

// or...

const result2 = [...arr2, ...arr1]; // -> [3, 4, 5, 0, 1, 2]

2 Comments

How efficient is this? From what I have tested this is very slow for arrays containing objects, see: jsperf.com/array-concat-vs-array-push-vs-array-spread/1
unluckily this link doesn't work anymore :/
40

Use Array.prototype.concat.apply to handle multiple arrays' concatenation:

var resultArray = Array.prototype.concat.apply([], arrayOfArraysToConcat);

Example:

var a1 = [1, 2, 3],
    a2 = [4, 5],
    a3 = [6, 7, 8, 9];
Array.prototype.concat.apply([], [a1, a2, a3]); // [1, 2, 3, 4, 5, 6, 7, 8, 9]

1 Comment

I like this one! Works easily with a variable number of arrays to concatenate. +1
33

The concat() method is used to join two or more arrays. It does not change the existing arrays, it only returns a copy of the joined arrays.

array1 = array1.concat(array2, array3, array4, ..., arrayN);

2 Comments

Sometimes I hate JavaScript for not modyfying the original array. 🙄
@VincentHoch-Drei concat is specifically used for creating new arrays without mutating the original array. If you want to update array1, you'd have to use array1.push(...array2, ...array3, ...array4)
18

If you are in the middle of piping the result through map/filter/sort etc and you want to concat array of arrays, you can use reduce

let sorted_nums = ['1,3', '4,2']
  .map(item => item.split(','))   // [['1', '3'], ['4', '2']]
  .reduce((a, b) => a.concat(b))  // ['1', '3', '4', '2']
  .sort()                         // ['1', '2', '3', '4']

1 Comment

I like this approach best, but note that this is a hundred times slower than the [].concat.apply way.
11

Now we can combine multiple arrays using ES6 Spread. Instead of using concat() to concatenate arrays, try using the spread syntax to combine multiple arrays into one flattened array. eg:

var a = [1,2];
var b = [3,4];
var c = [5,6,7];
var d = [...a, ...b, ...c];
// resulting array will be like d = [1,2,3,4,5,6,7]

Comments

10

solved like this.

let arr = [[1, 2], [3, 4], [5, 6]];
 console.log([].concat(...arr));

Comments

10

Shorten with ES6.

new Set([].concat(...Array));

This does concat and unique the multiple arrays;

let Array = [
  ['vue','babel','npm','gulp','mysql','less','laravel'],
  ['jquery','react','js','css','wordpress','html','bootstrap'],
  ['vue','babel','npm','gulp','mysql','less','laravel'],
  ['angular','cms','js','css','graphql','nodejs','php'],
  ['severless','headless','js','css','design','photoshop','php'],
]

const Boom = new Set([].concat(...Array));


// This is not necessary 
let dStr = '';
Boom.forEach(e=>{
  dStr += e + ' ';
})
document.write(dStr);
<div class="result"></div>

4 Comments

it does but it removes duplicates.. what if i dont want to remove duplicate arrays ?
new Set() does remove duplicated items. Just remove it. [].concat(...Array)
i want to use new Set([].concat(...Array)); but i also want to remove duplicates along with it in a single expression. is it possible ?
Works perfectly. You can also use [...new Set([].concat(...myArray))] to return an array instead of a Set.
7

Merge Array with Push:

const array1 = [2, 7, 4];
const array2 = [3, 5,9];
array1.push(...array2);
console.log(array1)

Using Concat and Spread operator:

const array1 = [1,2];
const array2 = [3,4];

// Method 1: Concat 
const combined1 = [].concat(array1, array2);

// Method 2: Spread
const combined2 = [...array1, ...array2];

console.log(combined1);
console.log(combined2);

Comments

4

You can use jsperf.com site to compare perfomance. Here is link to concat.

Added comparison between:

var c = a.concat(b);

and:

var c = [];
for (i = 0; i < a.length; i++) {
    c.push(a[i]);
}
for (j = 0; j < b.length; j++) {
    c.push(b[j]);
}

The second is almost 10 times slower in chrome.

1 Comment

However, you can use push.apply(), which seems to be faster than concat() in all browsers except Chrome. See my answer.
4

Easily with the concat function:

var a = [1,2,3];
var b = [2,3,4];
a = a.concat(b);
>> [1,2,3,2,3,4]

1 Comment

Please keep in mind that this method is very inefficient, unfortunately jsperf.com/concat-small-arrays-vs-push-vs-loop
3

Here is a function by which you can concatenate multiple number of arrays

function concatNarrays(args) {
    args = Array.prototype.slice.call(arguments);
    var newArr = args.reduce( function(prev, next) {
       return prev.concat(next) ;
    });

    return newArr;
}

Example -

console.log(concatNarrays([1, 2, 3], [5, 2, 1, 4], [2,8,9]));

will output

[1,2,3,5,2,1,4,2,8,9]

Comments

3

If you have array of arrays and want to concat the elements into a single array, try the following code (Requires ES2015):

let arrOfArr = [[1,2,3,4],[5,6,7,8]];
let newArr = [];
for (let arr of arrOfArr) {
    newArr.push(...arr);
}

console.log(newArr);
//Output: [1,2,3,4,5,6,7,8];

Or if you're into functional programming

let arrOfArr = [[1,2,3,4],[5,6,7,8]];
let newArr = arrOfArr.reduce((result,current)=>{
    result.push(...current);
    return result;
});

console.log(newArr);
//Output: [1,2,3,4,5,6,7,8];

Or even better with ES5 syntax, without the spread operator

var arrOfArr = [[1,2,3,4],[5,6,7,8]];
var newArr = arrOfArr.reduce((result,current)=>{
    return result.concat(current);
});
console.log(newArr);
//Output: [1,2,3,4,5,6,7,8];

This way is handy if you do not know the no. of arrays at the code time.

Comments

1

try this:

i=new Array("aaaa", "bbbb");
j=new Array("cccc", "dddd");

i=i.concat(j);

5 Comments

@reggie, you both copy-pasted from the same source ;)
no I have check the info in the same link that you. ilovethecode.com/Javascript/Javascript-Tutorials-How_To-Easy/…
yeah...I guess we got it from the same source :D
at least @JAiro changed the array contents. @reggie didn't. :)
it is the same, the important thing is help people to resolve its problems :)
1

where 'n' is some number of arrays, maybe an array of arrays . . .

var answer = _.reduce(n, function(a, b){ return a.concat(b)})

Comments

1

If there are only two arrays to concat, and you actually need to append one of arrays rather than create a new one, push or loop is the way to go.

Benchmark: https://jsperf.com/concat-small-arrays-vs-push-vs-loop/

Comments

1

if the N arrays are gotten from the database and not hardcoded, the i'll do it like this using ES6

let get_fruits = [...get_fruits , ...DBContent.fruit];

1 Comment

The most elegant way in my opinion!
1

The fastest by a factor of 10 is to iterate over the arrays as if they are one, without actually joining them (if you can help it).

I was surprised that concat is slightly faster than push, unless the test is somehow unfair.

const arr1 = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'];
const arr2 = ['j', 'k', 'l', 'i', 'm', 'n', 'o', 'p', 'q', 'r', 's'];
const arr3 = ['t', 'u', 'v', 'w'];
const arr4 = ['x', 'y', 'z'];

let start;

// Not joining but iterating over all arrays - fastest
// at about 0.06ms
start = performance.now()

const joined = [arr1, arr2, arr3, arr4];

for (let j = 0; j < 1000; j++) {
  let i = 0;
  while (joined.length) {
    // console.log(joined[0][i]);
    if (i < joined[0].length - 1) i++;
    else {
      joined.shift()
      i = 0;
    }
  }
}

console.log(performance.now() - start);

// Concating (0.51ms).
start = performance.now()

for (let j = 0; j < 1000; j++) {
  const a = [].concat(arr1, arr2, arr3, arr4);
}

console.log(performance.now() - start);

// Pushing on to an array (mutating). Slowest (0.77ms)
start = performance.now()

const joined2 = [arr1, arr2, arr3, arr4];

for (let j = 0; j < 1000; j++) {
  const arr = [];
  for (let i = 0; i < joined2.length; i++) {
    Array.prototype.push.apply(arr, joined2[i])
  }
}

console.log(performance.now() - start);

You can make the iteration without joining cleaner if you abstract it and it's still twice as fast:

const arr1 = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'];
const arr2 = ['j', 'k', 'l', 'i', 'm', 'n', 'o', 'p', 'q', 'r', 's'];
const arr3 = ['t', 'u', 'v', 'w'];
const arr4 = ['x', 'y', 'z'];

function iterateArrays(arrays, onEach) {
  let i = 0;
  while (joined.length) {
    onEach(joined[0][i]);
    if (i < joined[0].length - 1) i++;
    else {
      joined.shift();
      i = 0;
    }
  }
}

// About 0.23ms.
let start = performance.now()

const joined = [arr1, arr2, arr3, arr4];

for (let j = 0; j < 1000; j++) {
  iterateArrays(joined, item => {
    //console.log(item);
  });
}

console.log(performance.now() - start);

Comments

1

You can use this -

let array2d = [[1, 2, 3], [5, 4], [7, 8]];

let array1d = array2d.reduce((merged, block) => {
                          merged.push(...block); 
                          return merged; 
                     }, []);

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

OR this which I liked from one of the answers above -

let array2d = [[1, 2, 3], [5, 4], [7, 8]];
console.log([].concat(...array2d)); // [1, 2, 3, 5, 4, 7, 8]

OR this which I discovered -

let array2d = [[1, 2, 3], [5, 4], [7, 8]];
console.log(array2d.join().split(',').map(Number); // [1, 2, 3, 5, 4, 7, 8]

Comments

0

It appears that the correct answer varies in different JS engines. Here are the results I got from the test suite linked in ninjagecko's answer:

  • [].concat.apply is fastest in Chrome 83 on Windows and Android, followed by reduce (~56% slower);
  • looped concat is fastest in Safari 13 on Mac, followed by reduce (~13% slower);
  • reduce is fastest in Safari 12 on iOS, followed by looped concat (~40% slower);
  • elementwise push is fastest in Firefox 70 on Windows, followed by [].concat.apply (~30% slower).

Comments

0

You can check this blog, here the performance for both push() and concat() has been compared. Also custom functions are made which performs better in specific scenario.

https://dev.to/uilicious/javascript-array-push-is-945x-faster-than-array-concat-1oki

Comments

0

Remember that concat array can also have duplicates, sorting of items.

Step 1

Concat the arrays

let insights = emptyInsights.concat(defaultInsights, softInsights);

Step 2

Remove the duplicates

insights = [...new Set(insights)];

Step 3

Sort the array

insights = insights.sort((a: Insight, b: Insight) =>
          a.publishedDate > b.publishedDate ? -1 : 1
        );

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.