[TOC]
# 简介
数组的扁平化,就是将一个嵌套多层的数组 array (嵌套可以是任何层数)转换为只有一层的数组。
举个例子,假设有个名为 flatten 的函数可以做到数组扁平化,效果就会如下:
~~~js
var arr = [1, [2, [3, 4]]];
console.log(flatten(arr)) // [1, 2, 3, 4]
~~~
# flat
ES6 为数组实例新增了`flat`方法,用于将嵌套的数组“拉平”,变成一维的数组。该方法返回一个新数组,对原数组没有影响。
`flat`默认只会 “拉平” 一层,如果想要 “拉平” 多层的嵌套数组,需要给`flat`传递一个整数,表示想要拉平的层数。
~~~
function flattenDeep(arr, deepLength){
return arr.flat(deelLength)
}
~~~
# 递归
~~~
function flatten1(arr) {
var result = []
for (var i = 0; i < arr.length; i++) {
if (Array.isArray(arr[i])) {
result.push.apply(result, flatten1(arr[i]))
// 也可以使用 concat,但会产生新数组
// result = result.concat(flatten1(arr[i]))
} else {
result.push(arr[i])
}
}
return result
}
~~~
# toString
如果数组的元素都是数字,那么我们可以考虑使用 toString 方法,因为:
~~~js
[1, [2, [3, 4]]].toString() // "1,2,3,4"
~~~
调用 toString 方法,返回了一个逗号分隔的扁平的字符串,这时候再 split,然后转成数字就可以实现扁平化。
然而这种方法使用的场景却非常有限,**如果数组是 [1, '1', 2, '2'] 的话,这种方法就会产生错误的结果**。
~~~
function flatten2(arr) {
return arr.toString().split(',').map(function (item) {
return +item
})
}
~~~
# recude
~~~
function flatten3(arr) {
return arr.reduce(function (prev, next) {
// 可以简写成
// return prev.concat(Array.isArray(next) ? flatten3(next) : next)
if (Array.isArray(next)) {
return prev.concat(flatten3(next))
} else {
return prev.concat(next)
}
}, [])
}
~~~
# ...
ES6 增加了扩展运算符,用于取出参数对象的所有可遍历属性,拷贝到当前对象之中:
~~~js
var arr = [1, [2, [3, 4]]];
console.log([].concat(...arr)); // [1, 2, [3, 4]]
~~~
我们用这种方法只可以扁平一层,但是顺着这个方法一直思考,我们可以写出这样的方法:
~~~
function flatten4 (arr) {
while(arr.some((item) => Array.isArray(item))) {
arr = [].concat(...arr)
}
return arr
}
~~~
# 参考资料
[JavaScript专题之数组扁平化](https://github.com/mqyqingfeng/Blog/issues/36#)