问题:如何实现数组扁平化?

数组扁平化是将多维数组转换为一维数组的过程,本文汇总多种实现方案及适用场景。


核心方案

方法时间复杂度空间复杂度特点
flat()O(n)O(n)最简洁,ES2019
reduceO(n²)O(n)兼容性好
while + concatO(n²)O(n)手动控制深度
toString + splitO(n)O(n)简单但不优雅

具体实现

1. flat()(推荐)

时间复杂度:O(n) | 空间复杂度:O(n)

// 扁平一层
[1, [2, 3]].flat(); // [1, 2, 3]
 
// 扁平所有层级
[1, [2, [3, [4]]]].flat(Infinity); // [1, 2, 3, 4]
 
// 兼容写法
const flatten = arr => arr.flat ? arr.flat(Infinity) : arr;

原理:ES2019 原生方法,参数为扁平层级

2. reduce

时间复杂度:O(n²) | 空间复杂度:O(n)

// 扁平指定层级
function flatten(arr, depth = Infinity) {
  return depth > 0
    ? arr.reduce((prev, cur) => {
        return prev.concat(Array.isArray(cur) ? flatten(cur, depth - 1) : cur);
      }, [])
    : arr;
}
 
// 使用
flatten([1, [2, [3, [4]]]]); // [1, 2, 3, 4]

原理:递归拼接数组元素

3. while + concat

时间复杂度:O(n²) | 空间复杂度:O(n)

function flatten(arr) {
  while (arr.some(item => Array.isArray(item))) {
    arr = arr.concat(...arr);
  }
  return arr;
}
 
// 使用
flatten([1, [2, [3, [4]]]]); // [1, 2, 3, 4]

原理:循环检查是否存在数组,逐层展开

4. toString + split

时间复杂度:O(n) | 空间复杂度:O(n)

function flatten(arr) {
  return arr.toString().split(',').map(Number);
}
 
// 使用
flatten([1, [2, [3, [4]]]]); // [1, 2, 3, 4]

原理:转字符串再分割(仅适合纯数字数组)


方案对比

方案优点缺点
flat()代码简洁,性能好需要 ES2019+
reduce兼容性好,可控深度代码稍复杂
while+concat无需指定深度性能较差
toString极简只能处理数字,会改变类型

面试追问

Q:如何实现深度限制的扁平化?

// 扁平2层
[1, [2, [3]]].flat(2); // [1, 2, [3]]

Q:如何手写 flat() polyfill?

function flat(arr, depth = 1) {
  if (depth <= 0) return arr;
  return arr.reduce((prev, cur) => {
    return prev.concat(Array.isArray(cur) ? flat(cur, depth - 1) : cur);
  }, []);
}

知识图谱


参考延伸

  • MDN: Array.prototype.flat()
  • LeetCode 344. Reverse String(数组操作相关)