自 ES2019 引入了一个新的数组方法 Array.prototype.flat(depth) , 该方法返回一个指定了 depth 的扁平化后的新数组,默认为一层扁平, 而填入 Infinite 就可以实现递归无限扁平。
这个方法可以让我们快速地扁平化一个数组,具体实现的原理我们可以用以下代码模拟。
此外, ES2015 引入的 generator 生成器函数,也提供了实现的空间。
let b = [1, [2, [3, 4, [5]]]];
// 浅(一)层扁平化
function _flatShallow(arr) {
return arr.reduce((acc, curr) => {
if (Array.isArray(curr)) {
acc.push(...curr);
return acc;
}
acc.push(curr);
return acc;
}, []);
}
// 递归无限扁平化
function _flatInfinite(arr) {
return arr.reduce((acc, curr) => {
if (Array.isArray(curr)) {
acc.push(..._flatInfinite(curr));
return acc;
}
acc.push(curr);
return acc;
}, []);
}
/**
* @function: _flat 扁平化数组
* @description: 扁平化数组(深度可定义)
* @param {Array<any>} arr 需要扁平化的数组
* @param {Number} depth 目标深度
* @return {FlattenArray} 扁平化后的数组
*/
function _flat(arr, depth) {
let currDepth = 0; // 当前深度
// 递归函数主体
function recur(arr, currDepth) {
currDepth++; // 每次深度增1
console.log("当前深度: ", currDepth);
if (currDepth > depth) {
return arr; // 大于目标深度即返回原数组
}
return arr.reduce((acc, curr) => {
if (Array.isArray(curr)) {
acc.push(...recur(curr, currDepth));
return acc;
}
acc.push(curr);
return acc;
}, []);
}
return recur(arr, currDepth);
}
console.log(_flatShallow(b)); // [ 1, 2, [ 3, 4, [ 5 ] ] ]
console.log(_flatInfinite(b)); // [ 1, 2, 3, 4, 5 ]
console.log(_flat(b, 2)); // [ 1, 2, 3, 4, 5 ]
/**
*
* @name 生成器函数的扁平化数组实现
* @param {any} ctx 上下文元素, 可能是 Array
*/
function* flatArrIter(ctx) {
if (Array.isArray(ctx)) {
// 遍历数组对象 检查元素是否是数组 如果是则递归地进行迭代器生成
for (let i = 0; i < arr.length; i++) {
// yield* 表示移交代码执行权给其他(生成器函数),这里就可以递归。
yield* flatArrIter(ctx[i]);
}
} else {
yield ctx;
}
}
const arr = ["a", ["b", ["c", ["d", "e"]]]];
const gen = flatArrIter(arr);
console.log([...gen]); [ 'a', 'b', 'c', 'd', 'e' ]
// 或者
for (const val of gen) {
console.log(val); // a b c d e
}