JavaScript中合并数组的N种方法


Posted in Javascript onSeptember 16, 2014

这是一篇简单的文章,关于JavaScript数组使用的一些技巧。我们将使用不同的方法结合/合并两个JS数组,以及讨论每个方法的优点/缺点。

让我们先考虑下面这情况:

var a = [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ];

var b = [ "foo", "bar", "baz", "bam", "bun", "fun" ];

很显然最简单的结合结果应该是:
[

   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有10,000个元素,而b也有一万个元素? C就会有2万个元素,所以a和b的内内存使用就会翻倍。

“没问题!”,你说。让它们被垃圾回收,把A和B设置为null,问题解决了!

a = b = null; // 'a'和'b'就被回收了

呵呵。对于只有几个元素的小数组,这没啥问题。但对于大数组,或者在内存有限的系统中需要经常重复这个过程,它其实还有很多改进的地方。

循环插入

好吧,让我们将一个数组的内容复制到另一个,使用: 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数组比较小?出于内存和速度的原因,你可能要把更小的a放到b的前面,。没问题,只需将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"]

功能技巧

不过for循环确实比较丑,而且不好维护。我们可以做的更好吗?

这是我们的第一次尝试,使用Array#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"]

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(...)一样都有这种问题。

有一种方法可以避免这种最大长度限制。

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

    }

}

等一下,我们的可读性倒退了。 就这样吧,可能会越改越差,呵。

Javascript 相关文章推荐
js函数调用的方式
May 06 Javascript
基于Node.js的JavaScript项目构建工具gulp的使用教程
May 20 Javascript
JavaScript必知必会(七)js对象继承
Jun 08 Javascript
javascript实现随机生成DIV背景色
Jun 20 Javascript
JS对大量数据进行多重过滤的方法
Nov 04 Javascript
原生js编写焦点图效果
Dec 08 Javascript
thinkphp标签实现bootsrtap轮播carousel实例代码
Feb 19 Javascript
基于vue实现分页/翻页组件paginator示例
Mar 09 Javascript
ES6 javascript中class类的get与set用法实例分析
Oct 30 Javascript
实例讲解v-if和v-show的区别
Jan 31 Javascript
JS实现的贪吃蛇游戏案例详解
May 01 Javascript
vue.js 解决v-model让select默认选中不生效的问题
Jul 28 Javascript
JavaScript的null和undefined区别示例介绍
Sep 15 #Javascript
JavaScript中变量声明有var和没var的区别示例介绍
Sep 15 #Javascript
JavaScript的arguments对象应用示例
Sep 15 #Javascript
avascript中的自执行匿名函数应用示例
Sep 15 #Javascript
JavaScript function 的 length 属性使用介绍
Sep 15 #Javascript
css与javascript跨浏览器兼容性总结
Sep 15 #Javascript
一个通过script自定义属性传递配置参数的方法
Sep 15 #Javascript
You might like
php调用shell的方法
2014/11/05 PHP
爱恋千雪-US-AscII加密解密工具(网页加密)下载
2007/06/06 Javascript
js获取当前路径的简单示例代码
2014/01/08 Javascript
node.js中的buffer.Buffer.byteLength方法使用说明
2014/12/10 Javascript
JavaScript学习笔记之基础语法
2015/01/22 Javascript
jQuery使用fadein方法实现渐出效果实例
2015/03/27 Javascript
基于ajax实现文件上传并显示进度条
2015/08/03 Javascript
学习javascript文件加载优化
2016/02/19 Javascript
详解Javascript继承的实现
2016/03/25 Javascript
微信小程序实现移动端滑动分页效果(ajax)
2017/06/13 Javascript
微信小程序左滑动显示菜单功能的实现
2018/06/14 Javascript
vue通过指令(directives)实现点击空白处收起下拉框
2018/12/06 Javascript
JavaScript中window和document用法详解
2020/07/28 Javascript
JS指定音频audio在某个时间点进行播放
2020/11/28 Javascript
[03:40]DOTA2英雄梦之声_第01期_炼金术士
2014/06/23 DOTA
python中from module import * 的一个坑
2014/07/20 Python
python自动登录12306并自动点击验证码完成登录的实现源代码
2018/04/25 Python
Python 中的Selenium异常处理实例代码
2018/05/03 Python
Python中正则表达式的用法总结
2019/02/22 Python
python json.dumps中文乱码问题解决
2020/04/01 Python
python实现录音功能(可随时停止录音)
2020/10/26 Python
matplotlib阶梯图的实现(step())
2021/03/02 Python
细说CSS3中box属性中的overflow-x属性和overflow-y属性值的效果
2014/07/21 HTML / CSS
CSS3实现时间轴效果
2016/07/11 HTML / CSS
有关HTML5 Video对象的ontimeupdate事件(Chrome上无效)的问题
2013/07/19 HTML / CSS
西班牙创意礼品和小工具网上商店:Curiosite
2016/07/26 全球购物
巴西最大的家电和百货零售商:Casas Bahia
2016/11/22 全球购物
Under Armour安德玛意大利官网:美国高端运动科技品牌
2020/01/16 全球购物
统计学专业毕业生的自我评价分享
2013/11/28 职场文书
财务出纳岗位职责
2014/02/03 职场文书
感恩节红领巾广播稿
2014/02/11 职场文书
环保倡议书
2014/04/14 职场文书
信息工作经验交流材料
2014/05/28 职场文书
公共艺术专业自荐信
2014/09/01 职场文书
基于tensorflow权重文件的解读
2021/05/26 Python
利用Python实现Picgo图床工具
2021/11/23 Python