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类中获取外部函数名的方法与代码
Sep 12 Javascript
javascript判断iphone/android手机横竖屏模式的函数
Dec 20 Javascript
javascript 保存文件到本地实现方法
Nov 29 Javascript
js 遍历json返回的map内容示例代码
Oct 29 Javascript
JS随机漂浮广告代码具体实例
Nov 19 Javascript
JQuery判断HTML元素是否存在的两种解决方法
Dec 26 Javascript
JavaScript实现向OL列表内动态添加LI元素的方法
Mar 21 Javascript
解决jQuery使用JSONP时产生的错误
Dec 02 Javascript
jQuery实现遍历复选框的方法示例
Mar 06 Javascript
微信小程序 跳转传递数据的实例
Jul 06 Javascript
Material(包括Material Icon)在Angular2中的使用详解
Feb 11 Javascript
js使用文件流下载csv文件的实现方法
Jul 15 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原生导出excel文件的两种方法(推荐)
2016/11/19 PHP
Thinkphp 框架基础之入口文件功能、定义与用法分析
2020/04/27 PHP
使用jquery实现select添加实现后台权限添加的效果
2011/05/28 Javascript
javascript操作JSON的要领总结
2012/12/09 Javascript
JS获取几种URL地址的方法小结
2014/02/26 Javascript
详解Javascript 装载和执行
2014/11/17 Javascript
js实现点击图片将图片地址复制到粘贴板的方法
2015/02/16 Javascript
基于zepto.js实现仿手机QQ空间的大图查看组件ImageView.js详解
2015/03/05 Javascript
浅谈jQuery 选择器和dom操作
2016/06/07 Javascript
javascript运算符——位运算符全面介绍
2016/07/14 Javascript
用js实现博客打赏功能
2016/10/24 Javascript
浅谈html转义及防止javascript注入攻击的方法
2016/12/04 Javascript
Bootstrap弹出框之自定义悬停框标题、内容和样式示例代码
2017/07/11 Javascript
vue.js计算属性computed用法实例分析
2018/07/06 Javascript
d3.js实现图形缩放平移
2019/12/19 Javascript
vue+axios 拦截器实现统一token的案例
2020/09/11 Javascript
Vue表单提交点击事件只允许点击一次的实例
2020/10/23 Javascript
vue实现轮播图帧率播放
2021/01/26 Vue.js
[04:52]第二届DOTA2亚洲邀请赛主赛事第一天比赛集锦:OG娜迦海妖放大配合谜团大中3人
2017/04/02 DOTA
[00:47]DOTA2荣耀之路6:玩不了啦!
2018/05/30 DOTA
[54:27]TNC vs Serenity 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/19 DOTA
Python给你的头像加上圣诞帽
2018/01/04 Python
opencv python 基于KNN的手写体识别的实例
2018/08/03 Python
Python定时任务APScheduler的实例实例详解
2019/07/22 Python
Python CVXOPT模块安装及使用解析
2019/08/01 Python
Groupon法国官方网站:特卖和网上购物高达-70%
2019/09/02 全球购物
开放系统互连参考模型
2016/06/29 面试题
税务专业毕业生自荐信
2013/11/10 职场文书
对标管理实施方案
2014/03/12 职场文书
2014年财政所工作总结
2014/11/22 职场文书
贷款承诺书
2015/01/20 职场文书
李强感恩观后感
2015/06/17 职场文书
2016年“我们的节日·清明节”活动总结
2016/04/01 职场文书
2016年小学中秋节活动总结
2016/04/05 职场文书
mysql 数据插入优化方法之concurrent_insert
2021/07/01 MySQL
解决mysql的int型主键自增问题
2021/07/15 MySQL