没有't seem to be a way to extend an existing JavaScript array with another array, i.e. to emulate Python' s extend
方法 .
我想实现以下目标:
>>> a = [1, 2]
[1, 2]
>>> b = [3, 4, 5]
[3, 4, 5]
>>> SOMETHING HERE
>>> a
[1, 2, 3, 4, 5]
我知道有一个 a.concat(b)
方法,但是它创建了一个新数组而不是简单地扩展第一个数组 . 当 a
明显大于 b
(即不复制 a
的算法)时,我想要一种有效工作的算法 .
注意:这与如何将某些内容附加到数组不重复? - 这里的目标是将一个数组的全部内容添加到另一个数组中,并“在适当的位置”执行,即不复制扩展数组的所有元素 .
14 回答
答案非常简单 .
Concat的行为与JavaScript字符串连接非常相似 . 它将返回您在调用函数的数组末尾放入concat函数的参数组合 . 关键是您必须将返回的值分配给变量,否则会丢失 . 所以举个例子
我喜欢上面描述的
a.push.apply(a, b)
方法,如果你想要,你总是可以像这样创建一个库函数:并像这样使用它
您可以创建一个polyfill for extend,如下所示 . 它会添加到数组中;就地并返回自己,以便您可以链接其他方法 .
我可以看到非常好的答案,这一切都取决于您的阵列大小,您的要求和目标 . 它可以以不同的方式完成 .
我建议使用JavaScript for循环:
console.log(a)
输出将是然后你可以自己做功能:
console.log(extendArray(a, b));
输出将是这些天我觉得最优雅的是:
MDN article on the spread operator在ES2015(ES6)中提到了这种不错的含糖方式:
请注意
arr2
可以't be huge (keep it under about 100 000 items), because the call stack overflows, as per jcdude'回答 .您应该使用基于循环的技术 . 此页面上基于使用
.apply
的其他答案可能会因大型阵列而失败 .一个相当简洁的基于循环的实现是:
然后,您可以执行以下操作:
当我们追加的数组很大时,DzinX's answer(使用push.apply)和其他基于
.apply
的方法失败(测试显示,对于我来说,大约在Chrome中大于150,000个条目,在Firefox中大于500,000个条目) . 您可以在this jsperf中看到此错误 .发生错误是因为在使用大数组作为第二个参数调用'Function.prototype.apply'时超出了调用堆栈大小 . (MDN记录了使用Function.prototype.apply超出调用堆栈大小的危险 - 请参阅 Headers 为"apply and built-in functions"的部分 . )
要与本页面上的其他答案进行速度比较,请查看this jsperf(感谢EaterOfCode) . 基于循环的实现与使用
Array.push.apply
的速度相似,但往往比Array.slice.apply
慢一点 .有趣的是,如果你追加的数组是稀疏的,那么上面基于_350333的方法可以利用稀疏性并且优于基于
.apply
的方法;如果你想自己测试一下,请查看this jsperf .顺便说一句,不要被诱惑(像我一样!)进一步缩短forEach实现:
因为这会产生垃圾结果!为什么?因为
Array.prototype.forEach
为它调用的函数提供了三个参数 - 这些参数是:(element_value,element_index,source_array) . 如果您使用"forEach(this.push, this)",所有这些都将被推送到您的第一个数组,每次迭代forEach
!如果你想使用jQuery,有$.merge()
例:
结果:a =
[1, 2, 3, 4, 5]
可以使用
splice()
来完成:但是尽管比较丑陋,它并不比
push.apply
快,至少在Firefox 3.0中没有 .合并两个以上数组的另一种解决方案
然后打电话和打印为:
输出将是:
Array [1, 2, 3, 4, 5, 6, 7]
更新2018年:更好的答案是我的新答案:a.push(... b) . 不要再投票了,因为它从来没有真正回答过这个问题,但它是2015年黑客入侵谷歌首次亮相:)
对于那些只是搜索"JavaScript array extend"并到达这里的人来说,你可以很好地使用
Array.concat
.Concat将返回一个新数组的副本,因为线程启动程序不想要 . 但你可能不在乎(当然对于大多数用途来说这样会很好) .
以扩展运算符的形式还有一些不错的ECMAScript 6糖:
(它也复制 . )
首先在JavaScript中使用
apply()
来帮助理解我们使用它的原因:Push期望要添加的项目列表数组 . 但是,
apply()
方法将函数调用的预期参数作为数组 . 这允许我们使用内置push()
方法轻松地将一个数组的元素push
转换为另一个数组 .想象一下你有这些数组:
并简单地这样做:
结果将是:
使用扩展运算符(“
...
”)可以在ES6中完成同样的事情,如下所示:目前所有浏览器都更短,更好但不完全支持 .
此外,如果要将所有内容从数组
b
移动到a
,在此过程中清空b
,您可以执行以下操作:结果如下:
结合答案......
这个解决方案对我有用(使用ECMAScript 6的扩展运算符):
.push方法可以使用多个参数,因此通过使用.apply将第二个数组的所有元素作为参数传递给
.push
,您可以获得所需的结果:或许,如果你认为它更清楚:
如果您的浏览器支持ECMAScript 6,您可以使用spread operator,它更紧凑和优雅:
请注意,如果数组
b
太长,所有这些解决方案都将失败并出现堆栈溢出错误(麻烦从大约100,000个元素开始,具体取决于浏览器) . 如果你不能保证b
足够短,你应该使用另一个答案中描述的基于循环的标准技术 .