JavaScript学习笔记:数组合并
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中有很多种,接下来看看各种实现方法。
Array.prototype.concat()方法
在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()方法
其实还可以使用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;
}
他们得到的结果都将是一样的。
数组的reduce()或reduceRight()方法
使用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]
。接下来看看怎么实现这样的数组合并效果。
Array.prototype.push()方法
先来看一个简单的方法,就是通过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]
Array.prototype.concat()
除了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()
同样的,还可以使用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方法
使用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学习笔记:数组去重》一文。
扩展阅读
- Merge/flatten an array of arrays in JavaScript?
- Flattening multidimensional Arrays in JavaScript
- 数组
reduce()
和reduceRight()
方法 - 数组的
concat()
、slice()
和splice()
方法 - 数组的
push()
、pop()
、shift()
和unshift()
方法 - 检测数组方法
- 数组去重
总结
这篇文章主要介绍了在JavaScript中通过push()
、concat()
和reduce()
等方法的组合,实现数组合并的功能。并且在此基础上结合《JavaScript学习笔记:数组去重》一文介绍的方法,还可以轻松的实现合并后的数组,把重复的数组项删除。
如果文中有不对之处或者你有更好的方案,欢迎在下面的评论中与我们一起分享。
如需转载,烦请注明出处:https://www.fedev.cn/javascript/merge-flatten-an-array-of-arrays-in-javascript.htmlZoom Lebron XI 11