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 相关文章推荐
javascript学习网址备忘
May 29 Javascript
拖动布局之保存布局页面cookies篇
Oct 29 Javascript
javascript高级学习笔记整理
Aug 14 Javascript
判断及设置浏览器全屏模式
Apr 20 Javascript
JavaScript将数字转换成大写中文的方法
Mar 23 Javascript
javascript制作的滑动图片菜单
May 15 Javascript
jQuery 跨域访问解决原理案例详解
Jul 09 Javascript
浅谈js中用$(#ID)来作为选择器的问题(id重复的时候)
Feb 14 Javascript
vue给input file绑定函数获取当前上传的对象完美实现方法
Dec 15 Javascript
AjaxUpLoad.js实现文件上传
Mar 05 Javascript
浅谈手写node可读流之流动模式
Jun 01 Javascript
详解新手使用vue-router传参时注意事项
Jun 06 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+dbfile开发小型留言本
2006/10/09 PHP
PHP中10个不常见却非常有用的函数
2010/03/21 PHP
PHP中有关长整数的一些操作教程
2019/09/11 PHP
laravel 时间格式转时间戳的例子
2019/10/11 PHP
PHP类的自动加载与命名空间用法实例分析
2020/06/05 PHP
js监控IE火狐浏览器关闭、刷新、回退、前进事件
2014/07/23 Javascript
BootStrap selectpicker
2016/06/20 Javascript
郁闷!ionic中获取ng-model绑定的值为undefined如何解决
2016/08/27 Javascript
Form表单按回车自动提交表单的实现方法
2016/11/18 Javascript
详解AngularJS验证、过滤器、指令
2017/01/04 Javascript
从零开始学习Node.js系列教程四:多页面实现数学运算的client端和server端示例
2017/04/13 Javascript
浅谈原生JS中的延迟脚本和异步脚本
2017/07/12 Javascript
Vue的Class与Style绑定的方法
2017/09/01 Javascript
js实现登录注册框手机号和验证码校验(前端部分)
2017/09/28 Javascript
vue 自定义 select内置组件
2018/04/10 Javascript
React通过redux-persist持久化数据存储的方法示例
2019/02/14 Javascript
vue+elementUI实现图片上传功能
2019/08/20 Javascript
关于layui的动态图标不显示的解决方法
2019/09/04 Javascript
layui富文本编辑器前端无法取值的解决方法
2019/09/18 Javascript
Postman动态获取返回值过程详解
2020/06/30 Javascript
JS实现悬浮球只在一侧滑动并且是横屏状态下
2020/08/19 Javascript
[02:43]DOTA2英雄基础教程 半人马战行者
2014/01/13 DOTA
讲解Python中的标识运算符
2015/05/14 Python
scrapy爬虫完整实例
2018/01/25 Python
Python使用遗传算法解决最大流问题
2018/01/29 Python
python Spyder界面无法打开的解决方法
2018/04/27 Python
django 使用 request 获取浏览器发送的参数示例代码
2018/06/11 Python
Python实现将Excel转换成为image的方法
2018/10/23 Python
解决Pycharm运行时找不到文件的问题
2018/10/29 Python
python在TXT文件中按照某一字符串取出该字符串所在的行方法
2018/12/10 Python
如何在windows下安装Pycham2020软件(方法步骤详解)
2020/05/03 Python
小 200 行 Python 代码制作一个换脸程序
2020/05/12 Python
带有css3动画效果的兼容多浏览器简单导航条示例
2014/01/26 HTML / CSS
毕业生银行实习自我鉴定
2014/10/14 职场文书
2014年大班保育员工作总结
2014/12/02 职场文书
情人节单身感言
2015/08/03 职场文书