Several ways of array flattening and their advantages and disadvantages

Preface

Whether you are doing a project or looking for a job, array flattening is an important knowledge skill.
In the ES10 released in 2019, js has added a flat API to the array: Array.protoytype.flat
will be given flat below. Several ways to achieve, by the way, talk about the advantages and disadvantages of these methods

1. Convert to string processing

The idea is to convert the array into a string, and filter out the brackets through join or regular replacement.
Join is a magical api. It will remove all the brackets in the string when it converts the array into a string, amazing~

function flatten1(arr) {
    if (!Array.isArray(arr)) return [] 
    return Array.prototype.join.call(arr).split(',')
}
function flatten2(arr1) {
    return JSON.stringify(arr1).replace(/\[|\]/g, '').split(',')
}

This trick is simple and rude, and it is very enjoyable to use, but it also fails in simple and rude — not all types can be perfectly restored after plastic surgery into a string.
Take serialization as an example. JSON is a commonly used data. The transmission format has good support for commonly used data carriers such as objects and arrays, but poor support for other reference types such as Map, Set, Date, etc. Therefore, when using serialization to achieve flat or deep copying, you need to follow The actual scene to judge the use

Suitable for use in scenarios where array elements are all strings or numbers

Two, recursively implement flat

Converting to a string is indeed cool to use, but there is also a problem of limited types of support.
Therefore, I advise young people to speak martial arts and not to be smart, ah, smart, Ma Lin should be diligent and practical. , Everyone should follow Ma Baoguo's teacher to learn orthodox martial arts~

function flatten3(arr) {
    let res = []
    arr.forEach(v => Array.isArray(v) ? res = res.concat(flatten3(v)) : res.push(v))
    return res
}

The above realization, the idea is fairly clear, but it seems that you can try a more concise way of realization

function flatten4(arr) {
    return Array.prototype.reduce.call(arr, (total, cur) => total.concat(Array.isArray(cur) ? flatten4(cur) : cur), [])
}

Recursive implementation can avoid the problem that the string type is not supported, but every time a function is called, some information, such as parameters, local variables, etc., will be stored in the stack. When the function is executed too many times, a stack overflow exception will be thrown. Therefore, it is necessary to discuss other implementation methods.

Three, non-recursive realization of flat

Here try to use while loop + queue to achieve non-recursive flat

function flatten5(arr) {
    let res = []
    while (true) {
        if (arr.length === 0) break
        let cur = arr.shift()
        Array.isArray(cur) ? arr.unshift(...cur) : res.push(cur)
    }
    return res
}

Four, ES10 flat realizes the flattening of the array of the specified depth

In ES10, the official native flat method supports the input of a depth parameter, try to implement it here

function flatten6(arr,depth = 1) {
    if (!Array.isArray(arr)) return []
    if(typeof depth !== 'number') depth = 1
    let curDepth = 1  
    function flat(arr,curDepth){
        return Array.prototype.reduce.call(arr, (total, cur) =>{
            // 无需扁平化的场景: 超过深度阈值 或 当前元素非数组
            if(curDepth > depth || !Array.isArray(cur)){
                total.push(cur)
                return total
            }else{
                curDepth ++
                return total.concat(flat(cur,curDepth))
            }
        }
        , [])
    }
    return flat(arr,curDepth)
}

test

Guess you like

Origin blog.csdn.net/qq_41109610/article/details/113577706