【JS】数组扁平化

62 阅读1分钟

方法一:普通递归

let arr = [0,[1,2,[3,4,5,[6,7,8,9]]]]
arr = flatten(arr)

function flatten(arr){
    let res = []
    let length = arr.length
    for(let i=0; i<length; i++){
        if(Array.isArray(arr[i]){
            // 向下递归
            res = res.concat(flatten(arr[i]))
        } else {
            res.push(arr[i])
        }
    }
    return res
}

console.log(arr)  // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

方法二:reduce 递归

let arr = [0,[1,2,[3,4,5,[6,7,8,9]]]]

arr = flatten(arr)

function flatten(arr){
    return arr.reduce((prev, curr, index, arr) => {
        return prev.concat(Array.isArray(curr) ? flatten(curr) : curr)
    }, [])
}

console.log(arr)  // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

方法三:some + 展开运算符

let arr = [0,[1,2,[3,4,5,[6,7,8,9]]]]

while(arr.some((value, index, arr) => Array.isArray(value))){
    arr = [].concat(...arr)
}

console.log(arr)  // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

方法四:toString + split + map

let arr = [0,[1,2,[3,4,5,[6,7,8,9]]]]

function flatten(arr){
    // toString 是把数组展开成字符串
    // split 是将字符串按 "," 分割成数组
    // map 是把数组里面的每一项字符串重新转换为数字
    return arr.toString().split(',').map(element => {
        return Number(element)
    });
}

arr = flatten(arr)
console.log(arr)  // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

方法五:JSON 方法 + 正则

let arr = [0,[1,2,[3,4,5,[6,7,8,9]]]]

function flatten(arr){
    // 转换为 JSON 字符串
    arrStr = JSON.stringify(arr)
    // 把 [ 和 ] 全部去掉
    arrStr = arrStr.replace(/(\[|\])/g, '');
    // 加上最外层的 [ ]
    arrStr = '[' + arrStr + ']'
    // 重新转回 JSON 格式,并返回
    return JSON.parse(arrStr)
}

arr = flatten(arr)
console.log(arr)  // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

方法六:ES6 中的 flat 方法

1. 在 Array.prototype 上
2. 传递一个参数,表示展开多少层,默认一层,全部展开则为 Infinity
3. 不改变原数组
4. 底层是借助 reduce 实现的
let arr = [0,[1,2,[3,4,5,[6,7,8,9]]]]

arr = arr.flat(Infinity)

console.log(arr)  // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
flat 底层实现
Array.prototype._flat = function(depth){
    // 如果是非数组 或者 展开深度 <= 0,直接原样返回
    if(!Array.isArray(this) || depth <= 0) return this
    
    return this.reduce((prev, curr) => {
        // 如果 curr 还是一个数组
        if(Array.isArray(curr)){
            return prev.concat(curr._flat(depth - 1))
        } else {
            return prev.concat(curr)
        }
    }, [])
}