合并JavaScript数组的N种方法
这是一篇简单的文章,关于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数组的N种方法的更多相关文章
- JavaScript数组的22种方法
原文:http://www.cnblogs.com/xiaohuochai/p/5682621.html javascript中数组的22种方法 前面的话 数组总共有22种方法,本文将其分为对象继 ...
- 遍历Javascript数组的一种方法!
应用场景: 如果您的数组只用一次的话就适用这种方法,因为遍历完后数组便清空了.代码如下: var arr=[1,5,6,2,3]; for(;i=arr.shift();){ console.log( ...
- JavaScript数组去重(5种方法)
// 数组去重 let arr = ['a', 'b', 'b', 1, 1, 'true', true, true, NaN, NaN, 'NaN', undefined, undefined, n ...
- JavaScript数组打平(4种方法)
let arr = [1, 2, [3, 4, 5, [6, 7, 8], 9], 10, [11, 12]]; flatten1 = arr => arr.flat(Infinity) fla ...
- python将两个数组合并成一个数组的两种方法的代码
内容过程中,把写内容过程中常用的内容收藏起来,下面的资料是关于python将两个数组合并成一个数组的两种方法的内容,希望能对小伙伴们有帮助. c1 = ["Red","G ...
- javascript数组常用的遍历方法
本篇文章给大家带来的内容是关于javascript数组常用的遍历方法(代码示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 前言 本文主要介绍数组常见遍历方法:forEach.m ...
- 在WebBrowser中执行javascript脚本的几种方法整理(execScript/InvokeScript/NavigateScript) 附完整源码
[实例简介] 涵盖了几种常用的 webBrowser执行javascript的方法,详见示例截图以及代码 [实例截图] [核心代码] execScript方式: 1 2 3 4 5 6 7 8 9 1 ...
- JQuery遍历json数组的3种方法
这篇文章主要介绍了JQuery遍历json数组的3种方法,本文分别给出了使用each.for遍历json的方法,其中for又分成两种形式,需要的朋友可以参考下 一.使用each遍历 $(functio ...
- 合并BIN文件的两种方法(转)
源:http://blog.chinaunix.net/uid-20745340-id-1878803.html 合并BIN文件的两种方法 在单片机的开发过程中,经常需要将两个单独的BIN文件合并成一 ...
随机推荐
- Flutter的原理及美团的实践
导读 Flutter是Google开发的一套全新的跨平台.开源UI框架,支持iOS.Android系统开发,并且是未来新操作系统Fuchsia的默认开发套件.自从2017年5月发布第一个版本以来,目前 ...
- Oracle win32_11gR2_client.zip
先将下载下来的ZIP文件解压,并运行setup.exe文件. 第一步:选择管理员(0MB)(A),然后点击下一步 第二步:选择语言,点击下一步 第三步:选择安装的路径,然后点击下一步 第四步:执行到第 ...
- [leetcode DP]64. Minimum Path Sum
一个m*n的表格,每个格子有一个非负数,求从左上到右下最短的路径值 和62,63两个值是同一个思路,建立dp表,记录每个位置到右下角的最短路径的值 class Solution(object): de ...
- 决策树算法(Bagging与随机森林)
Bagging算法: 将训练数据集进行N次Bootstrap采样得到N个训练数据子集,对每个子集使用相同的算法分别建立决策树,最终的分类(或回归)结果是N个决策树的结果的多数投票(或平均). 其中,B ...
- c语言scanf()停止接受输入及scanf("%c",&c)吃掉回车或者空格字符的问题
scanf()函数接收输入数据时,遇以下情况结束一个数据的输入:(不是结束该scanf函数,scanf函数仅在每一个数据域均有数据,并按回车后结束). ① 遇空格."回车& ...
- hdu 5251 包围点集最小矩形 ***
题意:小度熊有一个桌面,小度熊剪了很多矩形放在桌面上,小度熊想知道能把这些矩形包围起来的面积最小的矩形的面积是多少. 求个凸包,矩形的边一定在凸包上,枚举边,求最大值,即为所求,多年不拍几何,直接套了 ...
- hdu 4403 爆搜
题意:给一串数字,在其间加入若干加号和一个等号,问使等式成立的方案总数 if the digits serial is "1212", you can get 2 equation ...
- bzoj 3306
以1号节点为根,弄出DFS序,我们发现,对于一个询问:(rt,u),以rt为根,u节点的子树中的最小点权,我们可以根据rt,u,1这三个节点在同一条路径上的相对关系来把它转化为以1为根的在DFS序上的 ...
- Codeforces Round #356 (Div. 2) D. Bear and Tower of Cubes dfs
D. Bear and Tower of Cubes 题目连接: http://www.codeforces.com/contest/680/problem/D Description Limak i ...
- GIT(6)----fork和clone的区别,fetch与pull的区别
参考资料: [1].Git学习笔记:fork和clone的区别,fetch与pull的区别 [2].在Github和Git上fork之简单指南