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计数器 刷新1次加1次访问
Sep 20 Javascript
IE8对JS通过属性和数组遍历解析不一样的地方探讨
May 06 Javascript
js+css实现的圆角边框TAB选项卡滑动门代码分享(2款)
Aug 26 Javascript
Javascript将JSON日期格式化
Aug 23 Javascript
thinkjs之页面跳转同步异步操作
Feb 05 Javascript
微信小程序 开发经验整理
Feb 15 Javascript
js脚本编写简单刷票投票系统
Jun 27 Javascript
解决vue的变量在settimeout内部效果失效的问题
Aug 30 Javascript
解决element ui select下拉框不回显数据问题的解决
Feb 20 Javascript
postman自定义函数实现 时间函数的思路详解
Apr 17 Javascript
javascript+css实现进度条效果
Mar 25 Javascript
Ant Design moment对象和字符串之间的相互转化教程
Oct 27 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
全文搜索和替换
2006/10/09 PHP
在PHP中利用wsdl创建标准webservice的实现代码
2011/12/07 PHP
关于crontab的使用详解
2013/06/24 PHP
10个超级有用值得收藏的PHP代码片段
2015/01/22 PHP
PHP完全二叉树定义与实现方法示例
2017/10/09 PHP
Laravel使用消息队列需要注意的一些问题
2017/12/13 PHP
php-fpm添加service服务的例子
2018/04/27 PHP
Javascript miscellanea -display data real time, using window.status
2007/01/09 Javascript
jquery ajax学习笔记2 使用XMLHttpRequest对象的responseXML
2011/10/16 Javascript
jquery checkbox实现单选小例
2013/11/27 Javascript
Javascript动态引用CSS文件的2种方法介绍
2014/06/06 Javascript
使用js获取图片原始尺寸
2014/12/03 Javascript
javascript设计模式之中介者模式Mediator
2014/12/30 Javascript
JavaScrip调试技巧之断点调试
2015/10/22 Javascript
jQuery设置单选按钮radio选中/不可用的实例代码
2016/06/24 Javascript
JavaScript制作弹出层效果
2016/12/02 Javascript
详解webpack + vue + node 打造单页面(入门篇)
2017/09/23 Javascript
Vue验证码60秒倒计时功能简单实例代码
2018/06/22 Javascript
JS实现求字符串中出现最多次数的字符和次数示例
2019/07/05 Javascript
Python动态生成多维数组的方法示例
2018/08/09 Python
python得到单词模式的示例
2018/10/15 Python
对python中不同模块(函数、类、变量)的调用详解
2019/07/16 Python
python图形开发GUI库pyqt5的详细使用方法及各控件的属性与方法
2020/02/14 Python
Python logging模块进行封装实现原理解析
2020/08/07 Python
HTML5离线缓存Manifest是什么
2016/03/09 HTML / CSS
澳大利亚领先的孕妇服装品牌:Mamaway
2018/08/14 全球购物
一些Unix笔试题和面试题
2012/09/25 面试题
工程造价专业求职信
2014/07/17 职场文书
中共广东省委常委会党的群众路线教育实践活动整改方案
2014/09/23 职场文书
教师思想作风整顿个人剖析材料
2014/10/10 职场文书
维稳承诺书
2015/01/20 职场文书
项目技术负责人岗位职责
2015/04/13 职场文书
三八妇女节新闻稿
2015/07/17 职场文书
经典格言警句:没有热忱,世间便无进步
2019/11/13 职场文书
mysql分组后合并显示一个字段的多条数据方式
2022/01/22 MySQL
SQL Server删除表中的重复数据
2022/05/25 SQL Server