数组扁平化实现

用递归、reduce、flat 三种方式实现数组扁平化

问题

将多层嵌套的数组转换为一维数组,例如 [1, [2, [3, 4]]] 转换为 [1, 2, 3, 4]

解答

1. 递归实现

function flatten(arr) {
  let result = [];
  
  for (let item of arr) {
    if (Array.isArray(item)) {
      // 递归处理嵌套数组,合并结果
      result = result.concat(flatten(item));
    } else {
      result.push(item);
    }
  }
  
  return result;
}

// 测试
console.log(flatten([1, [2, [3, 4]]])); // [1, 2, 3, 4]

2. reduce 实现

function flatten(arr) {
  return arr.reduce((acc, item) => {
    // 是数组就递归,否则直接拼接
    return acc.concat(Array.isArray(item) ? flatten(item) : item);
  }, []);
}

// 测试
console.log(flatten([1, [2, [3, [4, 5]]]])); // [1, 2, 3, 4, 5]

3. 使用 flat 方法

// Infinity 表示展开任意深度
const result = [1, [2, [3, [4]]]].flat(Infinity);

console.log(result); // [1, 2, 3, 4]

// 指定展开深度
console.log([1, [2, [3]]].flat(1)); // [1, 2, [3]]
console.log([1, [2, [3]]].flat(2)); // [1, 2, 3]

4. 支持指定深度的实现

function flatten(arr, depth = 1) {
  if (depth < 1) return arr.slice();
  
  return arr.reduce((acc, item) => {
    if (Array.isArray(item) && depth > 0) {
      return acc.concat(flatten(item, depth - 1));
    }
    return acc.concat(item);
  }, []);
}

// 测试
console.log(flatten([1, [2, [3, [4]]]], 2)); // [1, 2, 3, [4]]
console.log(flatten([1, [2, [3, [4]]]], Infinity)); // [1, 2, 3, 4]

5. 迭代实现(栈)

function flatten(arr) {
  const stack = [...arr];
  const result = [];
  
  while (stack.length) {
    const item = stack.pop();
    if (Array.isArray(item)) {
      // 数组元素重新入栈
      stack.push(...item);
    } else {
      // 非数组元素加入结果(头部插入保持顺序)
      result.unshift(item);
    }
  }
  
  return result;
}

// 测试
console.log(flatten([1, [2, [3, 4]]])); // [1, 2, 3, 4]

关键点

  • Array.isArray() 判断是否为数组
  • 递归是最直观的思路,但要注意调用栈深度
  • reduce 写法更简洁,本质还是递归
  • flat(Infinity) 是最简单的方案,但要注意兼容性
  • 迭代实现用栈模拟递归,避免栈溢出