What is the most efficient way to concatenate N arrays?
What is the most efficient way to concatenate N arrays of objects in JavaScript?
The arrays are mutable, and the result can be stored i开发者_StackOverflow中文版n one of the input arrays.
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.
[].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.)
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]
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 ]
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]
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);
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']
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]
solved like this.
let arr = [[1, 2], [3, 4], [5, 6]];
console.log([].concat(...arr));
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>
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);
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.
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]
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]
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.
try this:
i=new Array("aaaa", "bbbb");
j=new Array("cccc", "dddd");
i=i.concat(j);
where 'n' is some number of arrays, maybe an array of arrays . . .
var answer = _.reduce(n, function(a, b){ return a.concat(b)})
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/
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];
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);
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]
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 byreduce
(~56% slower);- looped
concat
is fastest in Safari 13 on Mac, followed byreduce
(~13% slower); reduce
is fastest in Safari 12 on iOS, followed by loopedconcat
(~40% slower);- elementwise
push
is fastest in Firefox 70 on Windows, followed by[].concat.apply
(~30% slower).
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
精彩评论