Array.prototype.flat 扁平化数组的实现原理研究

自 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
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值