扁平化数组没听过?那应该听说过扁平化管理吧,这可是互联网公司面试时的通用话术。简单的说,扁平化就是减少层级,可根据需要减少一个层级,或者减少到只有一个层级。扁平化数组就是将多重嵌套的数组,重新整理成一维数组。接下来就来看看可以怎么实现这种效果吧。
思路
对于这个问题应该已经清晰明了了,如何使用js实现呢。首先我们来捋一下思路:
- 定义一个空数组arr=[]用来表示最终返回的结果,然后遍历当前数组
- 如果数组项是非数组类型,那么就将其添加到arr中
- 如果是数组类型,则递归遍历后添加到arr中
思路并不复杂,主要就是判断是不是数组类型以及递归调用。
开始
使用flat
flat
是数组对象新增的一个方法,可以直接调用来实现数组的深度扁平化,使用时需要传入需要扁平化的深度,默认为1,即只扁平化一层。
语法:
const newArr = arr.flat([depth])
例如:
const arr = [1,2,3,[4,5,[6]]];
console.log(arr.flat()); // [1,2,3,4,5,[6]],默认只扁平化一层
兼容性:
使用for循环+递归
既然是要遍历数组,那么使用for循环最直接的选择。我们可以使用for
、while
、forEach
来实现for循环,这次我们使用forEach
,其他的也差不多。结合递归,在遍历完原数组后,需要将数组项添加到新的数组中,我们可以使用push
、concat
、解构等方式来实现,这里我们选择使用push
。
完整代码如下:
function flatten(arr) {
const res = [];
arr.forEach(item => {
if (Array.isArray(item)) {
const flatItem = flatten(item)
flatItem.forEach(e => res.push(e))
} else {
res.push(item)
}
})
return res;
}
const arr = [1,2,[3,[4],5],6];
console.log(flatten(arr)); // [1,2,3,4,5,6]
上述代码也并不复杂,关键是要理解递归调用,即重复调用自身。有一点需要注意,我们判断数组项是不是数组,不能使用typeof []
的方式,因为这个只能得到是object
,并不确定是不是数组。因此我们可以使用Array.isArray([])
或者[] instanceof Array
来判断。
使用reduce+递归
除了使用for循环,我们还可以借助reduce
。如果对reduce
的使用还不熟悉的化,可以参考笔者之前的文章:你真的会使用reduce吗,这里我们重点讲怎么使用reduce
实现数组扁平化:
const flatten = (arr) => arr.reduce((a, b) => (Array.isArray(b) ? [...a, ...flatten(b)] : [...a, b]), []);
const arr = [1,2,[3,[4],5],6];
console.log(flatten(arr)); // [1,2,3,4,5,6]
使用reduce
会有一个"累加"的过程,就不用自己在调用push
的方法了。而且我们使用了解构,这样代码看上去就更加简洁了。
使用toString()?不推荐
掌握一些奇淫技巧的朋友们可能会发现,对于数组直接调用toString()
貌似也可以实现“扁平化”,其实这个是一个误区。数组的toString()
重写了对象Object的toString()
方法,结果就是把数组连接成一个字符串,这个效果和join()
很像。注意返回的是一个字符串,如果原数组就是简单的字符串构成还好,如果是数字,如果是对象、Map等,那么将得不到想要的结果,或者需要进一步转换。我们来看几个例子:
const arr = ['1','2', ['3', 'a', ['b']]];
console.log(arr.toString().split(',')); // ['1','2','3','a','b'],没问题
const arr = [1,2,[3,[4],5],6];
console.log(arr.toString().split(',')); // ['1','2','3','4','5','6'],有问题,原来是数字,现在变成了字符串。需要再次转换
console.log(arr.toString().split(',').map(item => +item)); // [1,2,3,4,5,6]
const arr = [1,2,{a: 3},[4,5]];
console.log(arr.toString().split(',')); // ['1','2','object Object', '4', '5'],有问题,数据已经发生改变,且无法转换
总结
本文总结了实现数组扁平化的常用方法,每一种实现方式都不复杂,关键是要理解递归调用。在这些方法中,除了使用flat()
函数,其实更推荐使用reduce
来实现数组扁平化。不仅功能上满足,而且写起来代码也更加简洁。