在JavaScript中连接N个对象数组的最有效的方法是什么?

数组是可变的,结果可以存储在一个输入数组中。


当前回答

似乎正确答案在不同的JS引擎中有所不同。以下是我从ninjagecko的答案中链接的测试套件中得到的结果:

[] .concat。apply在Windows和Android的Chrome 83中最快,其次是reduce(慢56%); 循环concat在Mac的Safari 13中是最快的,其次是reduce(大约慢13%); reduce在iOS上的Safari 12中是最快的,其次是循环concat(慢40%); elementwise push在Windows上的Firefox 70中最快,其次是[].concat。应用(速度慢30%)。

其他回答

这是一个函数,通过它可以连接多个数组

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

    return newArr;
}

的例子,

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

将输出

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

您可以使用jsperf.com站点来比较性能。这是concat的链接。

增加了以下之间的比较:

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

第二款在镀铬的情况下几乎要慢10倍。

最快的10倍是迭代数组,就像它们是一个数组一样,而不实际连接它们(如果可以的话)。

我很惊讶concat比push稍微快一点,除非测试不公平。

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

如果你抽象它,你可以让不加入的迭代更干净,它仍然是原来的两倍:

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

似乎正确答案在不同的JS引擎中有所不同。以下是我从ninjagecko的答案中链接的测试套件中得到的结果:

[] .concat。apply在Windows和Android的Chrome 83中最快,其次是reduce(慢56%); 循环concat在Mac的Safari 13中是最快的,其次是reduce(大约慢13%); reduce在iOS上的Safari 12中是最快的,其次是循环concat(慢40%); elementwise push在Windows上的Firefox 70中最快,其次是[].concat。应用(速度慢30%)。

新回答

对于多个数组和ES6的数组,使用

arr.flat();

例如:

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 ]

这将适用于节点> 11和现代浏览器。


旧的答案

(把它留在这里,以防旧版本的节点需要它):

对于多个数组和ES6的数组,使用

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

例如:

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 ]