实现数组扁平化flat方法

手写实现数组的flat方法,将多维数组转换为一维数组,支持指定扁平化深度

问题

数组扁平化是指将嵌套的多维数组转换为一维数组的过程。例如 [1, [2, [3, 4]]] 扁平化后变为 [1, 2, 3, 4]。需要实现一个 flat 方法,支持指定扁平化的深度,当深度为 Infinity 时完全扁平化。

解答

方法一:递归实现

/**
 * 数组扁平化 - 递归实现
 * @param {Array} arr - 需要扁平化的数组
 * @param {number} depth - 扁平化深度,默认为1
 * @returns {Array} 扁平化后的数组
 */
function flat(arr, depth = 1) {
  // 如果深度为0,直接返回原数组的浅拷贝
  if (depth === 0) {
    return arr.slice();
  }
  
  return arr.reduce((result, item) => {
    // 如果当前项是数组且深度大于0,递归处理
    if (Array.isArray(item)) {
      result.push(...flat(item, depth - 1));
    } else {
      result.push(item);
    }
    return result;
  }, []);
}

方法二:迭代实现

/**
 * 数组扁平化 - 迭代实现
 * @param {Array} arr - 需要扁平化的数组
 * @param {number} depth - 扁平化深度,默认为1
 * @returns {Array} 扁平化后的数组
 */
function flat(arr, depth = 1) {
  let result = arr.slice();
  
  // 根据深度循环处理
  while (depth > 0 && result.some(item => Array.isArray(item))) {
    result = [].concat(...result);
    depth--;
  }
  
  return result;
}

方法三:栈实现(支持无限深度)

/**
 * 数组扁平化 - 栈实现
 * @param {Array} arr - 需要扁平化的数组
 * @param {number} depth - 扁平化深度,默认为1
 * @returns {Array} 扁平化后的数组
 */
function flat(arr, depth = 1) {
  const stack = arr.map(item => [item, 0]); // [元素, 当前深度]
  const result = [];
  
  while (stack.length) {
    const [item, currentDepth] = stack.pop();
    
    // 如果是数组且未达到指定深度,继续展开
    if (Array.isArray(item) && currentDepth < depth) {
      // 逆序入栈,保证顺序正确
      for (let i = item.length - 1; i >= 0; i--) {
        stack.push([item[i], currentDepth + 1]);
      }
    } else {
      result.unshift(item); // 从前面插入保证顺序
    }
  }
  
  return result;
}

使用示例

// 示例1:基本使用
const arr1 = [1, [2, [3, 4]]];
console.log(flat(arr1));           // [1, 2, [3, 4]]
console.log(flat(arr1, 1));        // [1, 2, [3, 4]]
console.log(flat(arr1, 2));        // [1, 2, 3, 4]

// 示例2:完全扁平化
const arr2 = [1, [2, [3, [4, [5]]]]];
console.log(flat(arr2, Infinity)); // [1, 2, 3, 4, 5]

// 示例3:包含空位的数组
const arr3 = [1, 2, [3, 4, [5, 6, [7, 8]]]];
console.log(flat(arr3, 2));        // [1, 2, 3, 4, 5, 6, [7, 8]]

// 示例4:混合类型
const arr4 = [1, 'a', [2, 'b', [3, 'c']], null, undefined];
console.log(flat(arr4, 2));        // [1, 'a', 2, 'b', 3, 'c', null, undefined]

// 示例5:空数组和深度为0
const arr5 = [1, [2, 3]];
console.log(flat(arr5, 0));        // [1, [2, 3]]
console.log(flat([], Infinity));   // []

关键点

  • 递归终止条件:当深度为 0 时停止递归,或者当前元素不是数组时直接返回
  • 深度控制:每递归一层,深度减 1,确保只扁平化指定层数
  • 数组判断:使用 Array.isArray() 准确判断是否为数组类型
  • reduce 方法:利用 reduce 累积结果,配合扩展运算符 ... 展开数组
  • concat 方法[].concat(...result) 可以将数组中的第一层数组元素展开
  • 边界处理:处理空数组、深度为 0、深度为 Infinity 等特殊情况
  • 性能考虑:递归方法代码简洁但可能栈溢出,迭代方法性能更好,栈方法适合深层嵌套
  • 保持顺序:确保扁平化后元素的顺序与原数组一致