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

464

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.

13
  • 2
    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
    Commented Apr 22, 2012 at 21:35
  • 1
    @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.
    – Tim Down
    Commented Apr 22, 2012 at 22:12
  • 24
    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.
    – chbrown
    Commented Jul 14, 2012 at 3:28
  • 1
    An even more concise way is a.push(...b);
    – dinvlad
    Commented Jun 23, 2017 at 21:49
  • 1
    @dinvlad: True, but only in ES6 environments. I've added a note to my answer.
    – Tim Down
    Commented Jun 26, 2017 at 9:36
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
  • 3
    @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.
    – ninjagecko
    Commented Apr 22, 2012 at 21:38
  • IMO this is the most effective way to "merge" n arrays, well done Commented Mar 17, 2016 at 17:16
  • 1
    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.
    – jfriend00
    Commented Jul 9, 2016 at 16:05
  • 5
    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/…
    – Eydrian
    Commented Feb 3, 2017 at 10:53
  • 1
    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. Commented Aug 29, 2018 at 5:10
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
  • 1
    In addition you can remove duplicate elements by using newArr = Array.from(new Set(newArr));.
    – Darius
    Commented Apr 29, 2018 at 0:53
  • Why in typescript does this become any[]? The typing is there - weird. Commented Aug 9, 2019 at 4:32
  • This is actually pretty horribly inefficient at larger array volumes. jsperf.com/flatten-array-203948 [].concat.apply([], ...arr) performs vastly better at large volumes.
    – colemars
    Commented Sep 11, 2019 at 9:30
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
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
  • 2
    I like this one! Works easily with a variable number of arrays to concatenate. +1
    – Joel
    Commented Jul 17, 2015 at 11:07
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
  • 2
    Sometimes I hate JavaScript for not modyfying the original array. 🙄 Commented Oct 11, 2018 at 9:11
  • 1
    @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)
    – adiga
    Commented Sep 8, 2019 at 10:40
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
  • I like this approach best, but note that this is a hundred times slower than the [].concat.apply way.
    – Arnie97
    Commented Jan 5, 2022 at 6:36
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]
0
10

solved like this.

let arr = [[1, 2], [3, 4], [5, 6]];
 console.log([].concat(...arr));
0
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
  • it does but it removes duplicates.. what if i dont want to remove duplicate arrays ? Commented Jun 17, 2020 at 6:26
  • 1
    new Set() does remove duplicated items. Just remove it. [].concat(...Array)
    – ronaldtgi
    Commented Jun 18, 2020 at 8:44
  • 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 ? Commented Jun 18, 2020 at 9:07
  • 1
    Works perfectly. You can also use [...new Set([].concat(...myArray))] to return an array instead of a Set. Commented Apr 2, 2021 at 4:41
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);

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
  • However, you can use push.apply(), which seems to be faster than concat() in all browsers except Chrome. See my answer.
    – Tim Down
    Commented Feb 22, 2011 at 17:17
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
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]
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.

1

try this:

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

i=i.concat(j);
5
  • @reggie, you both copy-pasted from the same source ;)
    – I.devries
    Commented Feb 22, 2011 at 15:27
  • no I have check the info in the same link that you. ilovethecode.com/Javascript/Javascript-Tutorials-How_To-Easy/…
    – JAiro
    Commented Feb 22, 2011 at 15:27
  • yeah...I guess we got it from the same source :D
    – reggie
    Commented Feb 22, 2011 at 15:28
  • at least @JAiro changed the array contents. @reggie didn't. :)
    – dogbane
    Commented Feb 22, 2011 at 15:28
  • it is the same, the important thing is help people to resolve its problems :)
    – JAiro
    Commented Feb 22, 2011 at 15:29
1

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

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

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/

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
  • The most elegant way in my opinion! Commented Dec 22, 2020 at 17:48
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);

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]
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).
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

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
        );

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.