数组扁平化
前言
数组的扁平化,就是将多维数组转换成一维数组。
例如:[1, [2, 3, [4, 5]]] => [1, 2, 3, 4, 5]
。
接下来我们实现下这个扁平化的函数 flatten
。
递归
循环判断数组,如果该项类型还是数组,那么就递归调用方法。
let arr = [1, [2, 3, [4, 5]]]
function flatten (arr) {
let res = []
for (let i = 0, len = arr.length; i < len; i++) {
if (Array.isArray(arr[i])) {
res = res.concat(flatten(arr[i]))
} else {
res.push(arr[i])
}
}
return res
}
console.log(flatten(arr)) // [1, 2, 3, 4, 5]
reduce
我们可以使用 reduce 方法来简化上面代码。
function flatten (arr) {
return arr.reduce(function (acc, cur) {
return acc.concat(Array.isArray(cur) ? flatten(cur) : cur)
}, [])
}
console.log(flatten(arr)) // [1, 2, 3, 4, 5]
扩展运算符
function flatten (arr) {
while (arr.some(item => Array.isArray(item))) {
arr = [].concat(...arr)
}
return arr
}
console.log(flatten(arr)) // [1, 2, 3, 4, 5]
因为 [].concat(...arr)
这个只展开一层,所以我们需要循环判断数组类型进行展开。
flat
这是 ES6 提供扁平化数组的方法。
数组的成员有时还是数组,Array.prototype.flat() 用于将嵌套的数组「拉平」,变成一维的数组。该方法返回一个新数组,对原数据没有影响。
flat() 默认只会「拉平」一层,如果想要「拉平」多层的嵌套数组,可以将 flat() 方法的参数写成一个整数,表示想要拉平的层数,默认为1。
如果不管有多少层嵌套,都要转成一维数组,可以用 Infinity 关键字作为参数。
let arr = [1, [2, 3, [4, 5]]]
let flatten = arr.flat(Infinity)
console.log(flatten) // [1, 2, 3, 4, 5]
_.flatMapDeep
_.flatMapDeep()
是 lodash 库提供的数组扁平化方法。源码戳这里
其中的核心代码贴在下面,我们一起来学习下:
/**
* 数组扁平化核心方法
* @param {Array} array 待处理数组
* @param {number} depth 最大扁平化层次(最大递归深度)默认是 Infinity
* @param {boolean} [predicate=isFlattenable] 每次迭代调用的函数,而这个函数(isFlattenable)的作用是判断该项是否可以扁平化,依据主要是该项是否是数组或类数组。函数源码地址:https://github.com/lodash/lodash/blob/master/.internal/isFlattenable.js
* @param {boolean} [isStrict] 是否过滤非数组项
* @param {Array} [result=[]] 处理结果数组
* @returns {Array} 返回新的扁平化数组
*/
function baseFlatten (array, depth, predicate, isStrict, result) {
// => let pred = predicate || isFlattenable
predicate || (predicate = isFlattenable)
// => let res = result || []
result || (result = [])
if (array == null) {
return result
}
for (const value of array) {
if (depth > 0 && predicate(value)) {
if (depth > 1) {
// 递归地扁平数组(容易受到调用堆栈限制的影响)。
baseFlatten(value, depth - 1, predicate, isStrict, result)
} else {
result.push(...value)
}
} else if (!isStrict) {
result[result.length] = value
}
}
return result
}
结语
本文到这里就结束了。在日常开发中,数组扁平化还是比较常用的,希望看完本文对你有所帮助。