JavaScript中合并数组的N种方法
这是一篇简单的文章,关于JavaScript数组使用的一些技巧。我们将使用不同的方法结合/合并两个JS数组,以及讨论每个方法的优点/缺点。
让我们先考虑下面这情况:
vara=[1,2,3,4,5,6,7,8,9];
varb=["foo","bar","baz","bam","bun","fun"];
很显然最简单的结合结果应该是:
[
1,2,3,4,5,6,7,8,9,
"foo","bar","baz","bam""bun","fun"
]
concat(..)
这是最常见的做法:
varc=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有10,000个元素,而b也有一万个元素?C就会有2万个元素,所以a和b的内内存使用就会翻倍。
“没问题!”,你说。让它们被垃圾回收,把A和B设置为null,问题解决了!
a=b=null;//"a"和"b"就被回收了
呵呵。对于只有几个元素的小数组,这没啥问题。但对于大数组,或者在内存有限的系统中需要经常重复这个过程,它其实还有很多改进的地方。
循环插入
好吧,让我们将一个数组的内容复制到另一个,使用:Array#push(..)
//`b`onto`a`
for(vari=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数组比较小?出于内存和速度的原因,你可能要把更小的a放到b的前面,。没问题,只需将push(..)换成unshift(..)即可:
//`a`into`b`:
for(vari=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"]
功能技巧
不过for循环确实比较丑,而且不好维护。我们可以做的更好吗?
这是我们的第一次尝试,使用Array#reduce:
//`b`onto`a`:
a=b.reduce(function(coll,item){
coll.push(item);
returncoll;
},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);
returncoll;
},b);
b;//[1,2,3,4,5,6,7,8,9,"foo","bar","baz","bam","bun","fun"]
Array#reduce(..)和Array#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(..)方法在这里并不需要担心前面的反向排序。ES6的spead操作会更漂亮:a.push(...b)或b.unshift(...a
数组最大长度限制
第一个主要的问题是,内存使用量增长了一倍(当然只是暂时的!)被追加内容基本上是通过函数调用将元素复制到堆栈中。此外,不同的JS引擎都有拷贝数据长度的限制。
所以,如果数组有一百万个元素,你肯定会超出了push(...)或unshift(...)允许调用堆栈的限制。唉,处理几千个元素它会做得很好,但你必须要小心,不能超过合理的长度限值。
注意:你可以尝试一下splice(...),它跟push(...)和unshift(...)一样都有这种问题。
有一种方法可以避免这种最大长度限制。
functioncombineInto(a,b){
varlen=a.length;
for(vari=0;i<len;i=i+5000){
b.unshift.apply(b,a.slice(i,i+5000));
}
}
等一下,我们的可读性倒退了。就这样吧,可能会越改越差,呵。
相关文章
- Javascript数组排序sort方法和自定义排序方法
- JavaScript中数组Array方法详解[通俗易懂]
- JavaScript数组filter方法
- 【说站】JavaScript数组有哪些遍历方法
- 【说站】JavaScript数组中concat方法是什么
- JavaScript 数组常用属性和方法(上)
- JavaScript 数组常用属性和方法(下)
- Javascript客户端脚本的设计和应用
- javascript常用方法总结
- javascript函数调用的对象和方法
- JavaScript中去掉数组中的重复值的实现方法
- Javascript数组的排序sort()方法和reverse()方法
- javascript数组去重3种方法的性能测试与比较
- JavaScript获取和设置CheckBox状态的简单方法
- javascript数组快速打乱重排的方法
- javascript在子页面中函数无法调试问题解决方法
- javascript生成随机大小写字母的方法
- JavaScript格式化日期时间的方法和自定义格式化函数示例
- javascript数组操作总结和属性、方法介绍
- PHP中的多行字符串传递给JavaScript的两种方法
- javascript使用数组的push方法完成快速排序