Array.flat(数组扁平化)

10 小时前
/ ,
2

Array.flat(数组扁平化)

Array.prototype.flat 用于把多维数组“拍平”为一维数组(或指定深度的更低维数组)。

const newArr = arr.flat(depth);
// depth 可选,默认 1
// 返回新数组,原数组不变

一句话理解

  • flat(1):只展开一层
  • flat(2):展开两层
  • flat(Infinity):展开到不能再展开

行为细节(面试容易问)

1) 只会展开数组:元素是对象不会被展开。

2) 会跳过空位(holes)

[, 1, [2]].flat();
// => [1, 2]

3) flat 不做“深拷贝”

  • 如果元素是对象,拍平后仍然是同一个对象引用。

手写实现思路

常见两种写法:

  • 递归(直观):代码短,但深层嵌套可能导致调用栈过深
  • 迭代(栈/队列):更稳,不怕递归栈

下面实现尽量贴近原生语义:

  • 支持 depth,包括 Infinity
  • 跳过 holes(不会把 holes 当 undefined 放进结果)
  • 不建议默认覆盖 Array.prototype.flat(避免污染全局、与原生冲突)

实现 1:递归版(最常见)

export function flatRecursive<T>(arr: T[], depth: number = 1): any[] {
    const result: any[] = [];
    const maxDepth = depth === Infinity ? Number.POSITIVE_INFINITY : Math.max(0, depth);

    const walk = (input: any[], d: number) => {
        for (let i = 0; i < input.length; i++) {
            if (!(i in input)) continue; // 跳过 holes

            const item = input[i];
            if (Array.isArray(item) && d > 0) {
                walk(item, d - 1);
            } else {
                result.push(item);
            }
        }
    };

    walk(arr as any[], maxDepth);
    return result;
}

const arr = [1, [2, 3, [4, 5]], 1, 2, [6, 7]];
flatRecursive(arr, 1); // [1,2,3,[4,5],1,2,6,7]
flatRecursive(arr, 2); // [1,2,3,4,5,1,2,6,7]

实现 2:迭代版(避免递归栈)

思路:用栈保存“待处理项 + 剩余深度”,不断弹出处理。

export function flatIterative<T>(arr: T[], depth: number = 1): any[] {
    const maxDepth = depth === Infinity ? Number.POSITIVE_INFINITY : Math.max(0, depth);
    const stack: Array<{ value: any; depth: number }> = [];

    // 从后往前入栈,保证出栈后顺序与原数组一致
    for (let i = arr.length - 1; i >= 0; i--) {
        if (!(i in arr)) continue; // 跳过 holes
        stack.push({ value: (arr as any)[i], depth: maxDepth });
    }

    const result: any[] = [];
    while (stack.length) {
        const { value, depth: d } = stack.pop()!;
        if (Array.isArray(value) && d > 0) {
            for (let i = value.length - 1; i >= 0; i--) {
                if (!(i in value)) continue;
                stack.push({ value: value[i], depth: d - 1 });
            }
        } else {
            result.push(value);
        }
    }

    return result;
}

复杂度

设数组中可达元素总数为 nn(拍平后元素数量的量级):

  • 时间:O(n)O(n)
  • 空间:O(n)O(n)(结果数组 + 递归/栈开销)

常见坑点

  • depth = 0 时应该返回浅拷贝(不展开)。
  • 要注意 holes 行为:原生 flat 会移除 holes。
  • 超深嵌套建议用迭代版,避免递归调用栈溢出。

使用社交账号登录

  • Loading...
  • Loading...
  • Loading...
  • Loading...
  • Loading...