JavaScript中数组知识点很多,前面学习了一些基础知识。那么今天继续学习数组相关的知识。这篇文章主要是看在JavaScript中如何合并数组。
合并数组是一个相当常见,在实际使用的场景也有不同之处。比如说,我们有两个变量:
arr1 = [1,2]; arr2 = [3,4];
将数组 arr1
和 arr2
合并成一个数组 arr
:
arr = [1,2,3,4]
另外还有一种方式是将一个复合数组的数组项合并在一起,比如:
var myArray = [[1, 2],[3, 4, 5], [6, 7, 8, 9]];
将数组 myArray
的数组项合并在一起,变成想要的效果:
arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
我们先来考虑下面的这种情况,我们有两个(或多个)数组:
var arr1 = [1,2]; var arr2 = [3,4];
想要的结果是将 arr1
和 arr2
合并在一起,最终想要的结果是: [1,2,3,4]
。实现这样的效果,在JavaScript中有很多种,接下来看看各种实现方法。
在JavaScript中 Array.prototype.concat()
方法可以 传入的数组或非数组与原数组合并,并组成一个新数组再返回 。
如此一来就可以这样做:
var arr1 = [1,2]; var arr2 = [3,4]; var arr = arr1.concat(arr2); console.log(arr); // [1, 2, 3, 4]
将上面的代码封装到一个函数中,比如:
function flatten (arr1, arr2) { return arr1.concat(arr2); } flatten(arr1,arr2); // [1, 2, 3, 4]
正如你看到的,返回的结果是一个全新的数组,将数组 arr1
和 arr2
合并在一起,并且 arr1
和 arr2
不会有任何变化。是不是很简单。
不过这种方法将会有所限制,如果 arr1
和 arr2
数组元素都很多的话或者说内存有限的系统中经常重复这个过程,它其实还有很多改进的地方。
其实还可以使用 for
循环和 Array.prototype.push()
方法,将一个数组的内容复制到另一个。
function flatten (arr1, arr2) { for (var i = 0; i < arr2.length; i++) { arr1.push(arr2[i]); } return arr1; }
上面的方法将数组 arr2
中的每个元素复制到数组 arr1
中。现在数组 arr1
中有了数组 arr2
的元素。
有个小细节,如果数组 arr1
和 arr2
相比,数组 arr1
中的元素数量小于数组 arr2
时,出于内存和速度的原因,可以将更小的数组 arr1
放到数组 arr2
前面。在JavaScript中只需要将 Array.prototype.push()
方法换成 Array.prototype.unshift()
方法。
function flatten (arr1,arr2) { for (var i = arr1.length - 1; i >= 0; i--) { arr2.unshift(arr1[i]); } return arr2; }
他们得到的结果都将是一样的。
使用 for
循环看上去很丑而且又不好维护,其实使用 Array.prototype.reduce()
和 Array.prototype.reduceRight()
可以做得更好:
function flatten (arr1, arr2) { return arr2.reduce(function(prev, curr){ prev.push(curr); return prev; },arr1); }
或者
function flatten(arr1, arr2){ return arr1.reduceRight( function (prev, curr){ prev.unshift(curr); return prev; },arr2); }
上面这些方法都实现了想要的结果。但他们都有不同的限制,比如使用 push()
、 unshift()
、 reduce()
和 reduceRight()
只能针对两个数组合并,如果要将两个以上数组合并,就困难了。不过 concat()
方法可以将多个数组合并在一起。
有时候将两个或多个数组合并在一起的时候,还需要对合并后的相同的数组元素删除(数组去重)。在合并后的数组之后,再做一下数组去重,即可达到数组去重的效果:
function flatten(arr1,arr2){ var result = []; var arr = []; arr = arr2.reduce(function(prev, curr){ prev.push(curr); return prev; },arr1); for (var i = 0; i < arr.length; i++) { var index = arr[i]; if (result.indexOf(index) === -1) { result.push(index); } } return result; } flatten([1,2],[12,1,2,3,4]); // [1, 2, 12, 3, 4]
接下来看另外一种数组合并情形。首先有一个复合数组:
var myArray = [[1, 2],[3, 4, 5], [6, 7, 8, 9]];
现在想要做的就是将数组 myArray
中的子数组的数组项合并在一起,变成一个新数组: [1, 2, 3, 4, 5, 6, 7, 8, 9]
。接下来看看怎么实现这样的数组合并效果。
先来看一个简单的方法,就是通过 for
循环和 Array.prototype.push()
方法实现。
function flatten(arr) { var result = []; for (var i = 0; i < arr.length; i++) { for (var j = 0; j< arr[i].length; j++) { result.push(arr[i][j]); } } return result; } flatten([[1, 2],[3, 4, 5], [6, 7, 8, 9]]); //[1, 2, 3, 4, 5, 6, 7, 8, 9]
不过上面的方法:
flatten([[1, 2],[3, 4, 5], [6, 7, 8, 9],10]);
返回的值仍然是:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
而不是想要的:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
要完成上面的效果可以做一下改造:
function flatten(a, r) { if (!r) { r = []; } for (var i = 0; i < a.length; i++) { if (a[i].constructor == Array) { flatten(a[i], r); } else { r.push(a[i]); } } return r; } flatten([[1, 2],[3, 4, 5], [6, 7, 8, 9,[11,12,[12,13,[14]]]],10]); // =>[1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 12, 13, 14, 10]
除了 push()
方法,在JavaScript中可以使用 Array.prototype.concat()
方法来实现:
function flatten(arr){ var result = []; for (var i = 0; i < arr.length; i++) { result = result.concat(arr[i]); } return result; } flatten([[1, 2],[3, 4, 5], [6, 7, 8, 9]]);//[1, 2, 3, 4, 5, 6, 7, 8, 9] flatten([[1, 2],[3, 4, 5], [6, 7, 8, 9],10,11]);//[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
不过可以通过 Function.prototype.apply()
方法,让其变得更简单:
function flatten (arr) { return Array.prototype.concat.apply([], arr); }
还可以将上面的方法做个精简:
function flatten (arr) { return [].concat.apply([],arr); }
在ES6中,还可以这样写:
function flatten(arr) { return [].concat(...arr) }
另外让自己的代码变得更健壮,还可以添加一些判断:
function flatten(arr) { arr = Array.prototype.concat.apply([], arr); return arr.some(Array.isArray) ? flatten(arr) : arr; }
这样写,还可以实现三重或者更多重的数组合并:
flatten([[1, 2],[3, 4, 5], [6, 7, 8, 9,[11,12,[12]]],10]); // =>[1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 12, 10] flatten([[1, 2],[3, 4, 5], [6, 7, 8, 9,[11,12,[13]]],10]); // =>[1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 10]
或者:
function flatten (arr) { var isArray = Object.prototype.toString.call(arr) === '[object Array]'; if (isArray && arr.length > 0) { var head = arr[0]; var tail = arr.slice(1); return flatten(head).concat(flatten(tail)); } else { return [].concat(arr); } }
同样的,还可以使用 Array.prototype.reduce()
来实现同样的效果:
function flatten(arr) { return arr.reduce(function(flat, toFlatten) { return flat.concat(Array.isArray(toFlatten) ? flatten(toFlatten) : toFlatten); }, []); } flatten([[1, 2],[3, 4, 5], [6, 7, 8, 9]]); // => [1, 2, 3, 4, 5, 6, 7, 8, 9] flatten([[1, 2],[3, 4, 5], [6, 7, 8, 9,[10]]]); // => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
使用ES6方法:
function flatten(arr) { return [].concat(...arr) }
除了上面这种方法,还可以这样:
function deepFlatten(arr) { return flatten( // return shalowly flattened array arr.map(x => // with each x in array Array.isArray(x) // is x an array? ? deepFlatten(x) // if yes, return deeply flattened x : x // if no, return just x ) ) }
在上面的几种方法中,添加一些去重的代码,也可以很快实现。
function flatten(arr) { var newArr = arr.reduce(function(flat, toFlatten) { return flat.concat(Array.isArray(toFlatten) ? flatten(toFlatten) : toFlatten); }, []); var result; result = newArr.filter(function (ele,i,arr) { return newArr.indexOf(ele) === i; }); return result; } flatten([[1, 2],[3, 4, 5], [6, 7, 8, 9,[10,[12]]],11]); // => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 11] flatten([[1, 2],[3, 4, 5,[1,2,3,4,5]], [6, 7, 8, 9,[10,[12]]],11]); // => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 11]
有关于更多的数组去重方法,可以阅读《 JavaScript学习笔记:数组去重 》一文。
reduce()
和 reduceRight()
方法 concat()
、 slice()
和 splice()
方法 push()
、 pop()
、 shift()
和 unshift()
方法 这篇文章主要介绍了在JavaScript中通过 push()
、 concat()
和 reduce()
等方法的组合,实现 数组合并 的功能。并且在此基础上结合《 JavaScript学习笔记:数组去重 》一文介绍的方法,还可以轻松的实现合并后的数组,把重复的数组项删除。
如果文中有不对之处或者你有更好的方案,欢迎在下面的评论中与我们一起分享。
常用昵称“大漠”,W3CPlus创始人,目前就职于手淘。中国Drupal社区核心成员之一。对HTML5、CSS3和Sass等前端脚本语言有非常深入的认识和丰富的实践经验,尤其专注对CSS3的研究,是国内最早研究和使用CSS3技术的一批人。CSS3、Sass和Drupal中国布道者。2014年出版《 图解CSS3:核心技术与案例实战 》。