数组的扁平化
1. 什么是数组扁平化
所谓数组的扁平化, 就是指将一个有着多层嵌套数组转换成一个没有嵌套的数组. 例如: 将 [1, [2, 3], [4, [5, [6]]]] 转换成为 [1, 2, 3, 4, 5, 6]
const arr = [1, [2, 3], [4, [5, [6]]]]
arr.flat(3) //=> [1, 2, 3, 4, 5, 6]
2. 数组扁平化的实现
1. 最初实现
将传入的数组扁平化并返回
(function() {
function flatten(res = []) {
const array = this
for (let i = 0, len = array.length; i < len; i ++) {
const val = array[i]
if (Array.isArray(val)) { // 如果是数组的话, 就对其进行扁平化处理
val.flatten(res)
} else { // 如果不是数组, 则直接将元素放入 res 即可
res.push(val)
}
}
return res
}
Array.prototype.flatten = flatten
})()
const array = [1, 2, [3, [4, [5, 6, [7, 8]]]]]
array.flatten() //=> [1, 2, 3, 4, 5, 6, 7, 8]
2. 进一步实现
很容易发现, 和 JS 中的 flat 相比, 最初实现少了 depth 参数 (反嵌套的深度), 在此加上
(function() {
function flatten(depth = 1, res = []) {
const array = this
for (let i = 0, len = array.length; i < len; i ++) {
const val = array[i]
if (Array.isArray(val) && depth > 0) {
// 如果 val 是数组, 且需要进行扁平化处理
val.flatten(depth - 1, res)
} else {
res.push(val)
}
}
return res
}
Array.prototype.flatten = flatten
})()
const array = [1, 2, [3, [4, [5, 6, [7, 8]]]]]
array.flatten(3) //=> [1, 2, 3, 4, 5, 6, [7, 8]]
虽然去掉 res 参数后更接近 flat 函数, 但是为了防止每次执行 flatten 函数都要创建一个 res 数组, 每次接受递归的返回值时还需要对其进行一次展开, 既浪费时间, 又浪费空间, 故没有去掉 res 参数. 如下所示:
(function() {
function flatten(depth = 1) {
const array = this
const res = []
for (let i = 0, len = array.length; i < len; i ++) {
const val = array[i]
if (Array.isArray(val) && depth > 0) {
res.push(...val.flatten(depth - 1))
} else {
res.push(val)
}
}
return res
}
Array.prototype.flatten = flatten
})()
3. 最终实现
当 flatten 调用到 depth === 1 时, 直接利用扩展运算符添加到 res 数组即可, 提高程序效率
不然的话, 不仅需要再递归一层, 而且每遍历一个元素还得经历多次判断
(function() {
function flatten(depth = 1, res = []) {
const array = this
for (let i = 0, len = array.length; i < len; i ++) {
const val = array[i]
if (Array.isArray(val) && depth > 0) {
if (depth === 1) {
res.push(...val)
} else {
val.flatten(depth - 1, res)
}
} else {
res.push(val)
}
}
return res
}
Array.prototype.flatten = flatten
})()
const array = [1, 2, [3, [4, [5, 6, [7, 8]]]]]
array.flatten(3) //=> [1, 2, 3, 4, 5, 6, [7, 8]]
3. 数组扁平化的其他实现方向
1. 利用 Array.prototype.reduce 实现
(function() {
function flatten() {
const array = this
const res = array.reduce((prevVal, curVal) => {
return prevVal.concat(Array.isArray(curVal) ? curVal.flatten() : curVal)
}, [])
return res
}
Array.prototype.flatten = flatten
})()
2. 利用 Array.prototype.some 实现
(function() {
function flatten() {
const array = this
const res = [...array]
while (res.some(item => Array.isArray(item))) {
res = [].concat(...res)
}
return res
}
Array.prototype.flatten = flatten
})()
3. 利用 Array.prototype.splice 实现
(function() {
function flatten() {
const array = this
const res = [...array]
for (let i = 0; i < res.length; i ++) {
if (Array.isArray(res[i])) {
res.splice(i, 1, ...res[i])
i --
}
}
return res
}
Array.prototype.flatten = flatten
})()
4. 利用 stack 实现
(function() {
function flatten() {
const array = this
const stk = [...array]
const res = []
while (stk.length) {
let topVal = stk.pop()
if (Array.isArray(topVal)) {
stk.push(...topVal)
} else {
res.push(topVal)
}
}
return res.reverse()
}
Array.prototype.flatten = flatten
})()