转载

JavaScript学习笔记:数组合并

JavaScript中数组知识点很多,前面学习了一些基础知识。那么今天继续学习数组相关的知识。这篇文章主要是看在JavaScript中如何合并数组。

合并数组是一个相当常见,在实际使用的场景也有不同之处。比如说,我们有两个变量:

arr1 = [1,2]; arr2 = [3,4]; 

将数组 arr1arr2 合并成一个数组 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]; 

想要的结果是将 arr1arr2 合并在一起,最终想要的结果是: [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] 

正如你看到的,返回的结果是一个全新的数组,将数组 arr1arr2 合并在一起,并且 arr1arr2 不会有任何变化。是不是很简单。

不过这种方法将会有所限制,如果 arr1arr2 数组元素都很多的话或者说内存有限的系统中经常重复这个过程,它其实还有很多改进的地方。

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 的元素。

有个小细节,如果数组 arr1arr2 相比,数组 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学习笔记:数组去重 》一文介绍的方法,还可以轻松的实现合并后的数组,把重复的数组项删除。

如果文中有不对之处或者你有更好的方案,欢迎在下面的评论中与我们一起分享。

JavaScript学习笔记:数组合并

大漠

常用昵称“大漠”,W3CPlus创始人,目前就职于手淘。中国Drupal社区核心成员之一。对HTML5、CSS3和Sass等前端脚本语言有非常深入的认识和丰富的实践经验,尤其专注对CSS3的研究,是国内最早研究和使用CSS3技术的一批人。CSS3、Sass和Drupal中国布道者。2014年出版《 图解CSS3:核心技术与案例实战 》。

原文  http://www.w3cplus.com/javascript/merge-flatten-an-array-of-arrays-in-javascript.html
正文到此结束
Loading...