likes
comments
collection
share

假如有个面试题:你能用多少种方法实现数组扁平化?

作者站长头像
站长
· 阅读数 57

前言

什么是数组扁平化

数组扁平化是指将一个多维数组转换为一个一维数组的过程。

数组扁平化的五种方法

- 递归

- arr.flat(Infinity)

- toString --- 数组中只能有数字

- reduce --- 递归

- 解构 ...

递归

阶乘

例如:5! = 1 * 2 * 3 * 4 * 5,怎样通过一个方法实现阶乘?

for循环:

function mul(n) {
    let res = 1
    for(let i = 1; i <= n; i++) {
        res *= i
    }
    return res
}

console.log(mul(5))

打印结果

假如有个面试题:你能用多少种方法实现数组扁平化?

递归

function mul(n) {
    if(n == 1) return 1;
    return n * mul(n - 1);
}

console.log(mul(5));

打印结果

假如有个面试题:你能用多少种方法实现数组扁平化?

分析

假如有个面试题:你能用多少种方法实现数组扁平化?

第五层会返回1,给到第四层mul(1),第四层的值会返回到第三层mul(2),以此类推得到结果。 if(n == 1) return 1;这里必须要用到这行代码,不然mul()会被一直调用,mul(0)、mul(-1)、mul(-2)....直到爆栈。

假如有个面试题:你能用多少种方法实现数组扁平化?

递归函数两步走:

  • 找好公式(如:mul(n) = n * mul(n - 1))
  • 找到出口(如:if(n == 1) return 1;)

示例:

找到斐波那契数列第n个数:1 1 2 3 5 8 13 21 34 55 89 ...

第一步:fb(n) = fb(n - 1) + fb(n - 2),找到公式

第二步:if(n == 1 || n == 2) return 1;找到出口

function fb(n) {
    if(n ==1 || n == 2) return 1;
   return fb(n - 1) + fb(n - 2)
}

console.log(fb(10))

打印结果

假如有个面试题:你能用多少种方法实现数组扁平化?

flat()

用于将多维数组扁平化,即把一个嵌套的数组转换为一维数组。

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

const newArr = arr.flat(3)
console.log(newArr)

打印结果

假如有个面试题:你能用多少种方法实现数组扁平化?

万一我们不知道这个数组嵌套了几层呢?

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

const newArr = arr.flat(Infinity)
console.log(newArr)

打印结果

假如有个面试题:你能用多少种方法实现数组扁平化?

分析

通过Infinity无穷大,无论数组嵌套多少层,都能将该数组扁平化。

面试的时候如果让你手搓一个函数实现数组扁平化呢?

先介绍一下concat方法和解构

concat()方法

concat()方法是用于将两个或者多个数组进行合并,返回一个新的数组,原数组不会被改变。

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

console.log(arr.concat(arr2), arr);

打印结果

假如有个面试题:你能用多少种方法实现数组扁平化?

concat也可将某个值直接放入数组中

假如有个面试题:你能用多少种方法实现数组扁平化?

解构

从数组或对象中提取值并将其分配给不同变量,...x把剩余值以数组的形式赋给该变量,解构只能一层一层解。

let arr = [1, 2, 3, 4, 5]
let[a, b, ...arr2] = arr

console.log(a, b, arr2);

打印结果

假如有个面试题:你能用多少种方法实现数组扁平化?

也可使用解构来连接数组:

let arr = [1, 2, 3, 4, 5]
let arr2 = [6, 7, 8, 9]
let newArr = [...arr, ...arr2]
console.log(newArr);

打印结果

假如有个面试题:你能用多少种方法实现数组扁平化?

定义一个res空数组,使用一个for循环来遍历arr数组,再通过if判断语句,判断条件为Array.isArray(arr[i])方法判断arr数组内部的元素是否为数组,若为数组则递归调用flatten方法,否则直接将arr数组的元素push到res数组中,并且将再次遍历到的结果添加到res数组上,每次遍历到的数组res为[1, 2],[3, 4], [5],并且每次调用该函数函数时都会将res数组连接起来。

通过concat()方法

const arr = [1, 2, [3, 4, [5]]]
function flatten(arr) {
    let res = []
    
    for(let i = 0; i < arr.length; i++) {
        if (Array.isArray(arr[i])) {
           res = res.concat(flatten(arr[i]))
        } else {
            res.push(arr[i])
            console.log(res);
        }
    }
    return res
    
}
const newArr = flatten(arr)
console.log(newArr);

打印结果

假如有个面试题:你能用多少种方法实现数组扁平化?

通过解构方法

const arr = [1, 2, [3, 4, [5]]]
function flatten(arr) {
    let res = []
    
    for(let i = 0; i < arr.length; i++) {
        if (Array.isArray(arr[i])) {
        res = [...res, ...flatten(arr[i])]
        } else {
            res.push(arr[i])
        }
    }
    return res
    
}
const newArr = flatten(arr)
console.log(newArr);

打印结果

假如有个面试题:你能用多少种方法实现数组扁平化?

toString()和split()

  • toString方法能将数组(无论嵌套多少层)转换为字符串
  • 通过split方法以逗号为分隔符将上面的字符串变为数组
  • 通过map遍历数组,将数组内的元素转为Number类型
const arr = [1, 2, [3, 4, [5]]]

let str = arr.toString()

const newArr = str.split(',').map((item) => {
    return Number(item)
})

console.log(newArr);

打印结果

假如有个面试题:你能用多少种方法实现数组扁平化?

注:如果数组中元素类型不止有数字,不可使用toString()

const arr = [1, 2, 'abc', [3, 4, [5]]]

let str = arr.toString()

const newArr = str.split(',').map((item) => {
    return Number(item)
})

console.log(newArr);

打印结果

假如有个面试题:你能用多少种方法实现数组扁平化?

reduce() -- 本质也是递归

也是遍历数组内元素的方法

array.reduce(callbackFn(pre, item, index, arr){}, initialValue)

分析

reduce()里面接收两个参数,一个是回调函数callbackFn() {},一个是initialValue

回调函数callbackFn里面接收四个参数:

  • pre: 累计器累存回调的返回值;它是上一次调用回调时返回的累积值,或者是初始值(initialValue)。
  • item: 数组里的每个元素的值。
  • index: 当前遍历数组的索引。
  • arr: 当前遍历的数组。

initialValue:作为第一次调用 callbackFn 函数时 pre 的值。如果省略,则 pre 的初始值为数组的第一个元素,item 从第二个元素开始。 通过reduce遍历该数组,pre为上一次reduce的结果,所以pre+item可以实现将所有的数组中的值相加起来,initialValue为0,即pre初始为0,pre+item-->0+1 1+2 3+3 6+4 10+5 15+6 21+7,所以结果为28。

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

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

console.log(flatten(arr));

打印结果

假如有个面试题:你能用多少种方法实现数组扁平化?

Array.isArray(item) ? flatten(item) : item这是三元运算符,判断item是否为数组,若是递归调用flatten()函数,不是则把item加入到pre当中。

some()方法、解构和concat()方法实现数组扁平化

some(): 用于检测数组中的元素是否符合条件,数组中的至少有一个元素符合条件,符合返回true,否则,则返回false

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

let res = arr.some((item) => {
    return item > 5
})

console.log(res);

打印结果

假如有个面试题:你能用多少种方法实现数组扁平化?

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

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

console.log(flatten(arr));

打印结果

假如有个面试题:你能用多少种方法实现数组扁平化?

分析

通过some方法判断item是否为数组,如果是则通过解构将item解构再用concat方法连接起来,[1, 2, [3, 4, [5]]] => [1, 2, 3, 4, [5]] => [ 1, 2, 3, 4, 5 ]

结语

学会这五种方法,面试还不得嘎嘎拿下。

假如有个面试题:你能用多少种方法实现数组扁平化?

转载自:https://juejin.cn/post/7372100118578757683
评论
请登录