JavaScript数组合并的多种方法


Posted in Javascript onMay 22, 2016

这是一篇简单的文章,关于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 相关文章推荐
asp(javascript)全角半角转换代码 dbc2sbc
Aug 06 Javascript
类似GMAIL的Ajax信息反馈显示
Feb 16 Javascript
js导航菜单(自写)简单大方
Mar 28 Javascript
EasyUI中combobox默认值注意事项
Mar 01 Javascript
介绍JavaScript中Math.abs()方法的使用
Jun 14 Javascript
js生成随机数的过程解析
Nov 24 Javascript
深入浅析JavaScript中数据共享和数据传递
Apr 25 Javascript
AngularJS的ng-repeat指令与scope继承关系实例详解
Jan 21 Javascript
mui上拉加载功能实例详解
Apr 13 Javascript
angular2模块和共享模块详解
Apr 08 Javascript
Electron-vue脚手架改造vue项目的方法
Oct 22 Javascript
vue获取form表单的值示例
Oct 29 Javascript
浅析JavaScript回调函数应用
May 22 #Javascript
为什么JavaScript没有块级作用域
May 22 #Javascript
全面解析Bootstrap中nav、collapse的使用方法
May 22 #Javascript
全面解析bootstrap格子布局
May 22 #Javascript
Bootstrap模块dropdown实现下拉框响应
May 22 #Javascript
基于Bootstrap实现图片轮播效果
May 22 #Javascript
基于Vue.js的表格分页组件
May 22 #Javascript
You might like
php include加载文件两种方式效率比较
2010/08/08 PHP
php序列化函数serialize() 和 unserialize() 与原生函数对比
2015/05/08 PHP
PHP解密Unicode及Escape加密字符串
2015/05/17 PHP
jquery获取多个checkbox的值异步提交给php的方法
2015/06/24 PHP
PHP长网址与短网址的实现方法
2017/10/13 PHP
PHP 枚举类型的管理与设计知识点总结
2020/02/13 PHP
JavaScript 判断浏览器类型及版本
2009/02/21 Javascript
JavaScript高级程序设计(第3版)学习笔记 概述
2012/10/11 Javascript
JS前端框架关于重构的失败经验分享
2013/03/17 Javascript
IE与FF下javascript获取网页及窗口大小的区别详解
2014/01/14 Javascript
javascript学习笔记(三)BOM和DOM详解
2014/09/30 Javascript
Jquery ajax基础教程
2015/11/20 Javascript
基于jQuery实现点击最后一行实现行自增效果的表格
2016/01/12 Javascript
JavaScript基于面向对象实现的猜拳游戏
2018/01/03 Javascript
详解Axios 如何取消已发送的请求
2018/10/20 Javascript
vue路由守卫+登录态管理实例分析
2019/05/21 Javascript
node将geojson转shp返回给前端的实现方法
2019/05/29 Javascript
使用Bootstrap做一个朝代历史表
2019/12/10 Javascript
[01:21]DOTA2新纪元-7.0新版本即将开启!
2016/12/11 DOTA
python线程池的实现实例
2013/11/18 Python
Python序列之list和tuple常用方法以及注意事项
2015/01/09 Python
python僵尸进程产生的原因
2017/07/21 Python
HTML5学习心得总结(推荐)
2016/07/08 HTML / CSS
美国南加州的原创极限运动潮牌:Vans(范斯)
2016/08/05 全球购物
巴西最大的家电和百货零售商:Casas Bahia
2016/11/22 全球购物
C,C++的几个面试题小集
2013/07/13 面试题
先进事迹报告会感言
2014/01/24 职场文书
事务机电主管工作职责
2014/02/25 职场文书
文化产业实施方案
2014/06/07 职场文书
普通党员四风问题对照检查材料
2014/09/27 职场文书
写给领导的感谢信
2015/01/22 职场文书
中标通知书格式
2015/04/17 职场文书
涨价通知怎么写
2015/04/23 职场文书
2016大学生党校学习心得体会
2016/01/06 职场文书
《珍珠鸟》教学反思
2016/02/16 职场文书
创业不要错过,这4种餐饮新模式
2019/07/18 职场文书