扁平化数组的n种方式

172 阅读2分钟

前言

什么是扁平化数组?扁平化,顾名思义就是减少复杂性装饰,使其事物本身更简洁、简单,突出主题。 数组扁平化,对着上面意思套也知道了,就是将一个复杂的嵌套多层的数组,一层一层的转化为层级较少或者只有一层的数组

扁平化数组的n种方法

1. flat

利用ES6的flat方法:

flat() 方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。

const arr1 = [0, 1, 2, [3, 4]]
console.log(arr1.flat()) // [0, 1, 2, 3, 4]

const arr2 = [0, 1, 2, [[[3, 4]]]];
console.log(arr2.flat(2)) // [0, 1, 2, [3, 4]]

//使用 Infinity,可展开任意深度的嵌套数组
var arr3 = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]];
arr3.flat(Infinity) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

// flat()函数会自动清除列表中为空的元素
var arr4 = [1, 2, , 4, 5];
arr4.flat(); // [1,2,3,4]

2. reduce + concat

var arr = [1, 2, [3, 4]];

// 展开一层数组
arr.reduce((acc, val) => acc.concat(val), []) // [1, 2, 3, 4]

3. reduce + spread

使用扩展运算符

var arr = [1, 2, [3, 4]];

// 展开一层数组
const flattened = arr => [].concat(...arr)
console.log(flattened(arr)) // [1,2,3,4]

4. reduce + concat + isArray + recursivity

// 使用 reduce、concat 和递归展开无限多层嵌套的数组
var arr1 = [1, 2, 3, [1, 2, 3, 4, [2, 3, 4]]];
function flatDeep(arr, d = 1) {
   if (d > 0) {
    return arr.reduce((acc, val) => {
        return acc.concat(Array.isArray(val) ? flatDeep(val, d - 1) : val)
    }, [])
   } else {
       return arr.slice()
   }
};
flatDeep(arr1, Infinity); // [...]

5. forEach+isArray+push+recursivity

 // forEach 遍历数组会自动跳过空元素
const eachFlat = (arr = [], depth = 1) => {
    const result = []; // 缓存递归结果
    // 开始递归
    (function flat(arr, depth) {
        // forEach 会自动去除数组空位
        arr.forEach((item) => {
            // 控制递归深度
            if (Array.isArray(item) && depth > 0) {
                // 递归数组
                flat(item, depth - 1)
            } else {
                // 缓存元素
                result.push(item)
            }
        })
    })(arr, depth)
    // 返回递归结果
    return result;
}
var arr = [1, 2, [3, 4, [5, 6]]]
const flattened = eachFlat(arr) // [1, 2, 3, 4, [5, 6]]
const flattened2 = eachFlat(arr, Infinity) // [1, 2, 3, 4, 5, 6]

6. 使用堆栈 stack

// 无递归数组扁平化,使用堆栈
// 注意:深度的控制比较低效,因为需要检查每一个值的深度
// 也可能在 shift / unshift 上进行 w/o 反转,但是末端的数组 OPs 更快
var arr1 = [1, 2, 3, [1, 2, 3, 4, [2, 3, 4]]];

function flatten(input) {
    const stack = [...input];
    const res = [];
    while (stack.length) {
        // 使用 pop 从 stack 中取出并移除值
        const next = stack.pop();
        if (Array.isArray(next)) {
            // 使用 push 送回内层数组中的元素,不会改动原始输入
            stack.push(...next);
        } else {
            res.push(next);
        }
    }
    // 反转恢复原数组的顺序
    return res.reverse();
}
flatten(arr1); // [1, 2, 3, 1, 2, 3, 4, 2, 3, 4]

7. 使用迭代器

function* flatten(array) {
    for (const item of array) {
        if (Array.isArray(item)) {
            yield* flatten(item);
        } else {
            yield item;
        }
    }
}

var arr = [1, 2, [3, 4, [5, 6]]]
const flattened = [...flatten(arr)] // [1, 2, 3, 4, 5, 6]

8. join+split

function flat(arr) {
    return arr.join().split(',').map(item => parseInt(item))
}
var arr = [1, 2, [3, 4, [5, 6]]]
const flattened = flat(arr) // [1, 2, 3, 4, 5, 6]

9. toString+split

function flat(arr) {
    return arr.toString().split(',').map(item => parseInt(item))
}
var arr = [1, 2, [3, 4, [5, 6]]]
const flattened = flat(arr) // [1, 2, 3, 4, 5, 6]