How to extend an existing JavaScript array with another array, without creating a new array
似乎没有办法用另一个数组来扩展现有的javascript数组,即模仿Python的
我希望实现以下目标:
1 2 3 4 5 6 7 | >>> a = [1, 2] [1, 2] >>> b = [3, 4, 5] [3, 4, 5] >>> SOMETHING HERE >>> a [1, 2, 3, 4, 5] |
我知道有一个
注意:这不是如何将某些内容附加到数组的副本?--这里的目标是将一个数组的全部内容添加到另一个数组中,并"就地"执行,即不复制扩展数组的所有元素。
1 | >>> a.push(...b) |
如果您的浏览器不支持ecmascript 6,您可以使用
1 | >>> a.push.apply(a, b) |
或者,如果你觉得更清楚的话:
1 | >>> Array.prototype.push.apply(a,b) |
请注意,如果数组
update 2018:a better answer is a newer one of mine:
对于那些只搜索"javascript数组扩展"并到达这里的用户,您可以很好地使用
1 2 | var a = [1, 2, 3]; a = a.concat([5, 4, 3]); |
concat将返回新数组的副本,因为线程启动程序不需要。但是你可能不在乎(当然对于大多数用途来说,这是可以的)。
还有一些很好的ecmascript 6糖,以spread operator的形式:
1 2 | const a = [1, 2, 3]; const b = [...a, 5, 4, 3]; |
(它也复制。)
您应该使用基于循环的技术。本页上基于使用
一个相当简单的基于循环的实现是:
1 2 3 4 | Array.prototype.extend = function (other_array) { /* You should include a test to check whether other_array really is an array */ other_array.forEach(function(v) {this.push(v)}, this); } |
然后可以执行以下操作:
1 2 3 | var a = [1,2,3]; var b = [5,4,3]; a.extend(b); |
Dzinx的回答(使用push.apply)和其他基于
当以大数组作为第二个参数调用"function.prototype.apply"时,由于超出了调用堆栈大小,因此发生错误。(MDN注意到使用function.prototype.apply超过调用堆栈大小的危险-请参阅标题为"应用和内置函数"的部分。)
为了与本页上的其他答案进行速度比较,请查看这个JSperf(感谢eaterofcode)。基于循环的实现在速度上与使用
有趣的是,如果您要附加的数组是稀疏的,那么上面基于
顺便说一下,别被诱惑了(就像我以前那样!)要进一步缩短foreach实现,请执行以下操作:
1 2 3 | Array.prototype.extend = function (array) { array.forEach(this.push, this); } |
因为这会产生垃圾结果!为什么?因为
我觉得现在最优雅的是:
1 | arr1.push(...arr2); |
MDN关于Spread Operator的文章在ES2015(ES6)中提到了这种甜蜜的方式:
A better push
Example: push is often used to push an array to the end of an existing
array. In ES5 this is often done as:
1
2
3
4 var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
// Append all items from arr2 onto arr1
Array.prototype.push.apply(arr1, arr2);In ES6 with spread this becomes:
1
2
3 var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
arr1.push(...arr2);
请注意,根据jcdude的回答,
在javascript中,首先是几个关于
The
apply() method calls a function with a giventhis value, and
arguments provided as an array.
push需要向数组中添加一个项列表。但是,
假设您有这些数组:
1 2 | var a = [1, 2, 3, 4]; var b = [5, 6, 7]; |
只需这样做:
1 | Array.prototype.push.apply(a, b); |
结果将是:
1 | a = [1, 2, 3, 4, 5, 6, 7]; |
同样的事情也可以在ES6中使用如下的排列运算符("
1 | a.push(...b); //a = [1, 2, 3, 4, 5, 6, 7]; |
更短更好,但目前所有浏览器都不完全支持。
另外,如果要将所有内容从数组
1 2 3 | while(b.length) { a.push(b.shift()); } |
结果如下:
1 2 | a = [1, 2, 3, 4, 5, 6, 7]; b = []; |
如果您想使用jquery,这里有$.merge()。
例子:
1 2 3 | a = [1, 2]; b = [3, 4, 5]; $.merge(a,b); |
结果:a=
我喜欢上面描述的
1 2 3 4 | Array.prototype.append = function(array) { this.push.apply(this, array) } |
像这样使用
1 2 3 4 | a = [1,2] b = [3,4] a.append(b) |
使用
1 2 3 4 5 | b.unshift(b.length) b.unshift(a.length) Array.prototype.splice.apply(a,b) b.shift() // Restore b b.shift() // |
但是,尽管它比
此解决方案对我有效(使用ecmascript 6的spread运算符):
1 2 3 4 5 6 7 | let array = ['my', 'solution', 'works']; let newArray = []; let newArray2 = []; newArray.push(...array); // Adding to same array newArray2.push([...array]); // Adding as child/leaf/sub-array console.log(newArray); console.log(newArray2); |
您可以创建一个polyfill进行扩展,如下所示。它将添加到数组中;就位并返回自身,以便您可以链接其他方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | if (Array.prototype.extend === undefined) { Array.prototype.extend = function(other) { this.push.apply(this, arguments.length > 1 ? arguments : other); return this; }; } function print() { document.body.innerHTML += [].map.call(arguments, function(item) { return typeof item === 'object' ? JSON.stringify(item) : item; }).join(' ') + ' '; } document.body.innerHTML = ''; var a = [1, 2, 3]; var b = [4, 5, 6]; print('Concat'); print('(1)', a.concat(b)); print('(2)', a.concat(b)); print('(3)', a.concat(4, 5, 6)); print(' Extend'); print('(1)', a.extend(b)); print('(2)', a.extend(b)); print('(3)', a.extend(4, 5, 6)); |
1 2 3 4 | body { font-family: monospace; white-space: pre; } |
我能看到非常好的答案,这取决于你的数组大小,你的要求和目标。它可以用不同的方式来完成。
我建议使用javascript for循环:
1 2 3 4 5 6 | var a = [1, 2]; var b = [3, 4, 5]; for (i = 0; i < b.length; i++) { a.push(b[i]); } |
1 | Array [ 1, 2, 3, 4, 5 ] |
然后你就可以做你自己的功能了:
1 2 3 4 5 6 | function extendArray(a, b){ for (i = 0; i < b.length; i++) { a.push(b[i]); } return a; } |
1 | Array [ 1, 2, 3, 4, 5 ] |
组合答案…
1 2 3 4 5 6 7 8 9 | Array.prototype.extend = function(array) { if (array.length < 150000) { this.push.apply(this, array) } else { for (var i = 0, len = array.length; i < len; ++i) { this.push(array[i]); }; } } |
合并两个以上数组的另一种解决方案
1 2 3 4 5 6 7 8 9 10 11 12 13 | var a = [1, 2], b = [3, 4, 5], c = [6, 7]; // Merge the contents of multiple arrays together into the first array var mergeArrays = function() { var i, len = arguments.length; if (len > 1) { for (i = 1; i < len; i++) { arguments[0].push.apply(arguments[0], arguments[i]); } } }; |
然后调用并打印为:
1 2 | mergeArrays(a, b, c); console.log(a) |
输出为:
对于>150000条记录,使用
1 2 3 4 5 6 7 8 9 10 11 12 13 | if (!Array.prototype.extend) { Array.prototype.extend = function(arr) { if (!Array.isArray(arr)) { return this; } for (let record of arr) { this.push(record); } return this; }; } |
答案非常简单。
1 2 3 4 5 6 7 8 9 10 11 | >>> a = [1, 2] [1, 2] >>> b = [3, 4, 5] [3, 4, 5] >>> SOMETHING HERE (The following code will combine the two arrays.) a = a.concat(b); >>> a [1, 2, 3, 4, 5] |
concat的作用非常类似于javascript字符串串联。它将返回您在调用函数的数组末尾放入concat函数的参数的组合。关键是您必须将返回值赋给一个变量,否则它会丢失。例如
1 | a.concat(b); <--- This does absolutely nothing since it is just returning the combined arrays, but it doesn't do anything with it. |
超级简单,不依赖于扩散运算符或应用,如果这是一个问题。
1 | b.map(x => a.push(x)); |
在对此进行了一些性能测试之后,它的速度非常慢,但回答了有关不创建新数组的问题。concat的速度明显更快,甚至jquery的
https://jspef.com/merge-arrays19b/1