Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

数组扁平化 #11

Open
huitoutunao opened this issue Jul 11, 2021 · 0 comments
Open

数组扁平化 #11

huitoutunao opened this issue Jul 11, 2021 · 0 comments
Labels

Comments

@huitoutunao
Copy link
Owner

数组扁平化

前言

数组的扁平化,就是将多维数组转换成一维数组。

例如:[1, [2, 3, [4, 5]]] => [1, 2, 3, 4, 5]

接下来我们实现下这个扁平化的函数 flatten

递归

循环判断数组,如果该项类型还是数组,那么就递归调用方法。

let arr = [1, [2, 3, [4, 5]]]

function flatten (arr) {
    let res = []
    for (let i = 0, len = arr.length; i < len; i++) {
        if (Array.isArray(arr[i])) {
            res = res.concat(flatten(arr[i]))
        } else {
            res.push(arr[i])
        }
    }
    return res
}

console.log(flatten(arr)) // [1, 2, 3, 4, 5]

reduce

我们可以使用 reduce 方法来简化上面代码。

function flatten (arr) {
    return arr.reduce(function (acc, cur) {
        return acc.concat(Array.isArray(cur) ? flatten(cur) : cur)
    }, [])
}
console.log(flatten(arr)) // [1, 2, 3, 4, 5]

扩展运算符

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

因为 [].concat(...arr) 这个只展开一层,所以我们需要循环判断数组类型进行展开。

flat

这是 ES6 提供扁平化数组的方法。

数组的成员有时还是数组,Array.prototype.flat() 用于将嵌套的数组「拉平」,变成一维的数组。该方法返回一个新数组,对原数据没有影响。

flat() 默认只会「拉平」一层,如果想要「拉平」多层的嵌套数组,可以将 flat() 方法的参数写成一个整数,表示想要拉平的层数,默认为1。

如果不管有多少层嵌套,都要转成一维数组,可以用 Infinity 关键字作为参数。

let arr = [1, [2, 3, [4, 5]]]
let flatten = arr.flat(Infinity)
console.log(flatten) // [1, 2, 3, 4, 5]

_.flatMapDeep

_.flatMapDeep() 是 lodash 库提供的数组扁平化方法。源码戳这里

其中的核心代码贴在下面,我们一起来学习下:

/**
 * 数组扁平化核心方法
 * @param {Array} array 待处理数组
 * @param {number} depth 最大扁平化层次(最大递归深度)默认是 Infinity
 * @param {boolean} [predicate=isFlattenable] 每次迭代调用的函数,而这个函数(isFlattenable)的作用是判断该项是否可以扁平化,依据主要是该项是否是数组或类数组。函数源码地址:https://github.com/lodash/lodash/blob/master/.internal/isFlattenable.js
 * @param {boolean} [isStrict] 是否过滤非数组项
 * @param {Array} [result=[]] 处理结果数组
 * @returns {Array} 返回新的扁平化数组
*/
function baseFlatten (array, depth, predicate, isStrict, result) {
    // => let pred = predicate || isFlattenable
    predicate || (predicate = isFlattenable)
    // => let res = result || []
    result || (result = [])

    if (array == null) {
        return result
    }

    for (const value of array) {
        if (depth > 0 && predicate(value)) {
            if (depth > 1) {
                // 递归地扁平数组(容易受到调用堆栈限制的影响)。
                baseFlatten(value, depth - 1, predicate, isStrict, result)
            } else {
                result.push(...value)
            }
        } else if (!isStrict) {
            result[result.length] = value
        }
    }
    return result
}

结语

本文到这里就结束了。在日常开发中,数组扁平化还是比较常用的,希望看完本文对你有所帮助。

参考文献

JavaScript专题之数组扁平化

@huitoutunao huitoutunao added the 专题系列 JS专题 label Jul 11, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant