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 相关文章推荐
JQuery 确定css方框模型(盒模型Box Model)
Jan 22 Javascript
js 居中漂浮广告
Mar 21 Javascript
js 禁止选择功能实现代码(兼容IE/Firefox)
Apr 23 Javascript
JavaScript 基础篇之对象、数组使用介绍(三)
Apr 07 Javascript
javascript实现类似超链接的效果
Dec 26 Javascript
javascript实现控制文字大中小显示
Apr 28 Javascript
浅谈javascript获取元素transform参数
Jul 24 Javascript
JS控制文本域只读或可写属性的方法
Jun 24 Javascript
js 动态添加元素(div、li、img等)及设置属性的方法
Jul 19 Javascript
Bootstrap弹出框modal上层的输入框不能获得焦点问题的解决方法
Dec 13 Javascript
javaScript中&quot;==&quot;和&quot;===&quot;的区别详解
Mar 16 Javascript
JavaScript设计模式之单例模式原理与用法实例分析
Jul 26 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 IP转换整形(ip2long)的详解
2013/06/06 PHP
如何在PHP中使用正则表达式进行查找替换
2013/06/13 PHP
非常重要的php正则表达式详解
2016/01/04 PHP
js 创建快捷方式的代码(fso)
2010/11/19 Javascript
在标题栏显示新消息提示,很多公司项目中用到这个方法
2011/11/04 Javascript
使用Math.floor与Math.random取随机整数的方法详解
2013/05/07 Javascript
JavaScript获得url查询参数的方法
2015/07/02 Javascript
谈谈js中的prototype及prototype属性解释和常用方法
2015/11/25 Javascript
JSONObject使用方法详解
2015/12/17 Javascript
ZeroClipboard.js使用一个flash复制多个文本框
2017/06/19 Javascript
详解NODEJS基于FFMPEG视频推流测试
2017/11/17 NodeJs
详解vue2.0+vue-video-player实现hls播放全过程
2018/03/02 Javascript
记录一次完整的react hooks实践
2019/03/11 Javascript
基于vue和websocket的多人在线聊天室
2020/02/01 Javascript
javascript实现前端成语点击验证优化
2020/06/24 Javascript
[01:09]DOTA2次级职业联赛 - ishow.HMM战队宣传片
2014/12/01 DOTA
[01:10:24]DOTA2-DPC中国联赛 正赛 VG vs Aster BO3 第一场 2月28日
2021/03/11 DOTA
通过python下载FTP上的文件夹的实现代码
2013/02/10 Python
windows下安装python paramiko模块的代码
2013/02/10 Python
Python实现拼接多张图片的方法
2014/12/01 Python
合并百度影音的离线数据( with python 2.3)
2015/08/04 Python
Python二进制串转换为通用字符串的方法
2018/07/23 Python
python 判断linux进程,并杀死进程的实现方法
2019/07/01 Python
Python批量将图片灰度化的实现代码
2020/04/11 Python
python3代码中实现加法重载的实例
2020/12/03 Python
AVON雅芳官网:世界上最大的美容化妆品公司之一
2016/11/02 全球购物
3个CCIE对一个工程师的面试题
2012/05/06 面试题
音乐表演专业毕业生求职信
2013/10/14 职场文书
个人优缺点自我评价
2014/01/27 职场文书
体操比赛口号
2014/06/10 职场文书
小学阳光体育活动总结
2014/07/05 职场文书
机关党员进社区活动总结
2014/07/05 职场文书
挂职锻炼个人总结
2015/03/05 职场文书
2015年节能降耗工作总结
2015/05/22 职场文书
2016优秀班主任个人先进事迹材料
2016/02/26 职场文书
鲲鹏 CentOS 7 安装Python3.7
2022/05/11 Servers