# Array flatten

# 题目

写一个函数,实现 Array flatten 扁平化,只减少一个嵌套层级
例如输入 [1, 2, [3, 4, [100, 200], 5], 6] 返回 [1, 2, 3, 4, [100, 200], 5, 6]

# 解答

  • 遍历数组
  • 如果 item 是数字,则累加
  • 如果 item 是数组,则 forEach 累加其元素

代码参考 array-flatten.ts

# 连环问:如果想要彻底扁平,忽略所有嵌套层级?

像 lodash flattenDepth (opens new window) ,例如输入 [1, 2, [3, 4, [100, 200], 5], 6] 返回 [1, 2, 3, 4, 100, 200, 5, 6]

最容易想到的解决方案就是递归

/**
 * 数组深度扁平化,使用 push
 * @param arr arr
 */
export function flattenDeep1(arr: any[]): any[] {
    const res: any[] = [];

    arr.forEach((item) => {
        if (Array.isArray(item)) {
            const flatItem = flattenDeep1(item); // 递归
            flatItem.forEach((n) => res.push(n));
        } else {
            res.push(item);
        }
    });

    return res;
}

/**
 * 数组深度扁平化,使用 concat
 * @param arr arr
 */
export function flattenDeep2(arr: any[]): any[] {
    let res: any[] = [];

    arr.forEach((item) => {
        if (Array.isArray(item)) {
            const flatItem = flattenDeep2(item); // 递归
            res = res.concat(flatItem);
        } else {
            res = res.concat(item);
        }
    });

    return res;
}

# 单元测试

import { flattenDeep1, flattenDeep2 } from './array-flatten-deep'
describe('数组深度扁平化', () => {
    it('空数组', () => {
        const res = flattenDeep2([])
        expect(res).toEqual([])
    })

    it('非嵌套数组', () => {
        const arr = [1, 2, 3]
        const res = flattenDeep2(arr)
        expect(res).toEqual([1, 2, 3])
    })

    it('一级嵌套', () => {
        const arr = [1, 2, [10, 20], 3]
        const res = flattenDeep2(arr)
        expect(res).toEqual([1, 2, 10, 20, 3])
    })

    it('二级嵌套', () => {
        const arr = [1, 2, [10, [100, 200], 20], 3]
        const res = flattenDeep2(arr)
        expect(res).toEqual([1, 2, 10, 100, 200, 20, 3])
    })

    it('三级嵌套', () => {
        const arr = [1, 2, [10, [100, ['a', [true],'b'], 200], 20], 3]
        const res = flattenDeep2(arr)
        expect(res).toEqual([1, 2, 10, 100, 'a', true, 'b', 200, 20, 3])
    })
})

还有一种 hack 的方式 toString —— 但遇到引用类型的 item 就不行了。

const nums = [1, 2, [3, 4, [100, 200], 5], 6]
nums.toString() // '1,2,3,4,100,200,5,6'

// 但万一数组元素是 {x: 100} 等引用类型,就不可以了