JavaScript 中合并数组的两种方法
这是关于 JavaScript 技术快速简单的后。我们要结合/合并两个 JavaScript 数组的方法不同,以及各自的优点/缺点的方法。
让我们开始的场景:
var a = [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]; var b = [ "foo", "bar", "baz", "bam", "bun", "fun" ];
简单的合并数组 A
和 B
的,很明显应该是这样:
[1,2,3,4,5,6,7,8,9,"foo","bar","baz","bam","bun","fun"]
Concat
最常见的方法是:
var c = a.concat( b ); a; // [1,2,3,4,5,6,7,8,9] b; // ["foo","bar","baz","bam","bun","fun"] c; // [1,2,3,4,5,6,7,8,9,"foo","bar","baz","bam","bun","fun"]
正如你所看到的,C
是一种全新的数组表示两者的合并数组 A
和 B 的结果,A
和 B
两个数组本身没有变化。
如果 A 数组有 10000 项,B 数组也是 10000 个项目,那么 C 现在是 20000 项,基本上翻了一番,构成的内存使用情况 A 和 B。
也许你也想到了下面的方法,回收内存垃圾。
a = b = null; // `a` and `b` can go away now
只有几个小的数组这个方法是很好的。但是如果遇到大的数组,或是重复这一过程,经常有很多次,或工作在内存有限的环境中,它有很多不足之处。
循环插入
也许我们可以添加一个 array
的内容到其他数组里面,使用 push()
:
// `b` onto `a` for (var i=0; i < b.length; i++) { a.push( b[i] ); } a; // [1,2,3,4,5,6,7,8,9,"foo","bar","baz","bam","bun","fun"] b = null;
现在 A 既有原始的结果又加上了 B 内容,能更好的使用内存了。
但如果 A
小 B
进行比较非常大的?两个内存和速度的原因,你可能会想把小 A
到前面的 B
而不是再 B
到结束 A
。没问题,只是 push()
与 unshift(..)
在相反方向的:
// `a` into `b`: for (var i=a.length-1; i >= 0; i--) { b.unshift( a[i] ); } b; // [1,2,3,4,5,6,7,8,9,"foo","bar","baz","bam","bun","fun"] a = null;
功能上的技巧
for
循环是丑陋的和难以维持。我们可以做的更好吗?这是我们的第一次尝试,使用 reduce
:
// `b` onto `a`: a = b.reduce( function(coll,item){ coll.push( item ); return coll; }, a ); a; // [1,2,3,4,5,6,7,8,9,"foo","bar","baz","bam","bun","fun"] // or `a` into `b`: b = a.reduceRight( function(coll,item){ coll.unshift( item ); return coll; }, b ); b; // [1,2,3,4,5,6,7,8,9,"foo","bar","baz","bam","bun","fun"]
reduce()
和 reduceRight()
是好的,但他们有点笨拙的。ES6 =>
箭头的函数将瘦身略有下降,但它仍然需要每项调用一个函数,这是不幸的。
// `b` onto `a`: a.push.apply( a, b ); a; // [1,2,3,4,5,6,7,8,9,"foo","bar","baz","bam","bun","fun"] // or `a` into `b`: b.unshift.apply( b, a ); b; // [1,2,3,4,5,6,7,8,9,"foo","bar","baz","bam","bun","fun"]
这是一个正确的要好很多,特别是自从 unshift()
方法在这里并不需要担心相反的顺序在以前的尝试。将 6 的传播算子是更好的:a.push( ...b )
或 b.unshift( ...a )
。
但是事情并非像玫瑰一样看起来。在这两种情况下,通过 A
或 B
对 apply()
第二论点(或通过 ... 传播算子)意味着阵列被分散作为函数的参数。
第一个主要的问题是,我们有效地增加一倍的大小(暂时的,当然!)这件事被添加到基本上是将其内容复制到堆栈函数调用。此外,不同的JS引擎有不同的实现依赖性的参数,可以通过数。
所以如果 array
加上有一百万项,你几乎肯定超过允许的,堆栈的push(..)
或unshift(..)
打电话。呃。这将为几千元工作的很好,但是你必须小心,不要超过一个合理的安全限制。
注意:你可以试着同样的事情splice(..)
但是,你也会有相同的结论push(..)
/ unshift(..)
。
一种选择是使用这种方法,但批了段在最大安全的大小:
function combineInto(a,b) { var len = a.length; for (var i=0; i < len; i=i+5000) { b.unshift.apply( b, a.slice( i, i+5000 ) ); } }
我们从可读性倒退(甚至表现!)。以前让我们放弃我们的收益到目前为止退出。
总结
concat(..)
是尝试和真实的方法相结合的两个(或更多!)阵列。但隐藏的危险是,它创造了一个新的数组,而不是修改一个现有的。
有选择,修改的地方,但他们有不同的权衡。
给各种的优缺点,也许是最好的所有的选项(包括其他未显示)是 reduce(..)
和 reduceRight(..)
。
无论你选择什么,它批判地思考你的数组合并策略而不是想当然的可能是一个好主意。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论