连接N个数组的最有效方法是什么?


Answers:


323

如果要连接两个以上的数组,concat()那么这样做是为了方便和可能的性能。

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

对于仅连接两个数组,可以使用push接受多个包含要添加到数组中的元素的参数的事实来代替将一个数组中的元素添加到另一个数组的末尾而无需生成新数组。使用slice()它也可以代替它,concat()但是这样做似乎没有性能优势

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

在ECMAScript 2015及更高版本中,这可以进一步减少到

a.push(...b)

但是,对于大型数组(大约100,000个成员或更多),似乎将元素数组传递给push(使用apply()或ECMAScript 2015扩展运算符)的技术可能会失败。对于此类阵列,使用循环是一种更好的方法。有关详细信息,请参见https://stackoverflow.com/a/17368101/96100


1
我相信您的测试可能有一个错误:该a.concat(b)测试用例似乎不必要地复制了数组,a然后将其丢弃。
ninjagecko 2012年

1
@ninjagecko:你是对的。我更新了它:jsperf.com/concatperftest/6。对于创建连接两个现有阵列的新阵列的特殊情况,它看起来concat()通常更快。对于将数组连接到适当的现有数组的情况,这push()是要走的路。我更新了答案。
蒂姆·唐

16
我可以证明,使用push.apply方法使用多个新数组扩展单个数组比简单的concat调用具有巨大的性能优势(〜100x)。在v8 / node.js中,我正在处理很长的整数短列表。
chbrown

1
更简洁的方法是a.push(... b);
dinvlad

1
@dinvlad:是的,但仅在ES6环境中。我在回答中添加了注释。
蒂姆·唐

158
[].concat.apply([], [array1, array2, ...])

编辑:效率证明:http : //jsperf.com/multi-array-concat/7

edit2:Tim Supinie在评论中提到,这可能导致解释器超出调用堆栈的大小。这可能取决于js引擎,但我至少在Chrome上也达到了“超出最大调用堆栈大小”。测试案例:[].concat.apply([], Array(300000).fill().map(_=>[1,2,3]))。(使用当前接受的答案我也遇到了相同的错误,因此有人在预料这种用例或为其他用例建立一个库,无论您选择哪种解决方案,都可能需要进行特殊测试。)


3
@ c69:至少与在Chrome上重复.push(#,#,...,#)的选择答案一样有效。jsperf.com/multi-array-concat Tim Down选择的答案也可能有错误。此链接是按要求连接多个阵列(不只是2个)的性能比较;测试了多种可能的长度。
ninjagecko 2012年

IMO这是“合并” n个数组的最有效方法,做得很好
Eric Uldall 2016年

当N提前未知时,例如当您具有任意长度的数组的数组并且您希望它们全部串联在一起时,此答案特别有用。
jfriend00 '16

3
使用ES6和散布运算符,它变得更加简单:[] .concat(... [array1,array2,...])好吧,后三个点有点不幸。前三个是传播运算符 developer.mozilla.org/en/docs/Web/JavaScript/Reference/…–
Eydrian

Eydrian:我本人尝试避免使用扩展运算符,因为它效率很低,但是我不确定这是否是因为实现不成熟,或者es6规范的语义需要一些繁重的工作(即它将永远不会变得更好) )。在这种情况下,还没有运行任何基准测试。
ninjagecko


28

concat()方法用于连接两个或多个数组。它不会更改现有数组,只会返回已连接数组的副本。

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

1
有时我讨厌JavaScript不修改原始数组。🙄–
文森特·霍克·德雷

@ VincentHoch-Drei concat专门用于创建新数组而无需更改原始数组。如果要更新array1,则必须使用array1.push(...array2, ...array3, ...array4)
adiga

24

使用Array.prototype.concat.apply处理多个数组的串联:

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

例:

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
我喜欢这一个!使用可变数量的数组进行连接很容易。+1
乔尔2015年

14

如果您在通过map / filter / sort等将结果传递到管道中,并且想要连接数组数组,则可以使用 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']

14

对于多个数组和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 ]

1
此外,您可以使用删除重复的元素newArr = Array.from(new Set(newArr));
Darius M.

为什么在打字稿中变成any[]?在那里打字-很奇怪。
Simon_Weaver

实际上,在更大的阵列容量下,这效率极低。 jsperf.com/flatten-array-203948 [].concat.apply([], ...arr)在大批量运行时表现要好得多。
colemars

7

现在,我们可以使用组合多个数组ES6 Spread。而不是concat()用来连接数组,请尝试使用传播语法将多个数组组合为一个扁平数组。例如:

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]

5

这样解决。

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

完美的解决方案。
凌晨

4

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

之间增加了比较:

var c = a.concat(b);

和:

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

第二个是铬的慢将近十倍。


但是,您可以使用push.apply(),它似乎比concat()Chrome浏览器以外的所有浏览器都要快。看我的答案。
蒂姆·唐


3

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

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]

2

如果您有数组数组,并且想要将元素合并为一个数组,请尝试以下代码(需要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];

或者如果您正在从事函数式编程

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

甚至在没有扩展运算符的情况下使用ES5语法甚至更好

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

如果您不知道否,这种方式很方便。代码时的数组数量。


2

用ES6缩短。

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

这确实可以连接唯一化多个数组。

Codepen上的演示


它可以,但是可以删除重复的数组..如果我不想删除重复的数组怎么办?
Krunal Shah

new Set()确实删除重复的项目。只需将其删除。[].concat(...Array)
ronaldtgi

我想使用新的Set([]。concat(... Array)); 但我也想在单个表达式中删除重复项。可能吗 ?
Krunal Shah

2

合并数组

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

使用ConcatSpread运算符:

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


1

其中'n'是一些数组,也许是arrays的数组。。。

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



0

试试这个:

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

i=i.concat(j);

@reggie,你们俩都是从同一来源复制粘贴的;)
I.devries

不,我已经在与您相同的链接中检查了信息。 ilovethecode.com/Javascript/Javascript-Tutorials-How_To-Easy/…– JAiro
2011年

是的...我想我们是从同一来源获得的:D
reggie 2011年

至少@JAiro更改了数组的内容。@reggie没有。:)
dogbane

一样,重要的是帮助人们解决其问题:)
JAiro 2011年

0

如果N个数组是从数据库中获取的,而不是硬编码的,那么我将使用ES6这样做

let get_fruits = [...get_fruits , ...DBContent.fruit];
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.