js中从递归到数组的扁平化

1,830 阅读4分钟

前言

数组的扁平化在面试中是经典的考题,在js中要实现扁平化数组有多种方法。接下来就请和我一起来看看怎样去实现数组的扁平化。

我们先来认识一下递归

递归

什么是递归?

递归是一种算法思想,用一句话概括为在运行的过程中不断地调用自己,有点像俄罗斯套娃的意思。递归有两个过程,简单地说一个是递的过程,一个是归的过程。

一个经典例子:使用递归求数的阶乘

// 递归   找规律   找出口
function mul(n) {

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

console.log(mul(5));

使用递归解决问题我们可以简单地概括为两步,第一步是找规律,第二步是找出口。就比如上面的代码,我们可以先找到以下规律:

// mul(5) ==> 5 * mul(4)
// mul(4) ==> 4 * mul(3)
// mul(3) ==> 3 * mul(2)
// mul(2) ==> 2 * mul(1)
// mul(1) == 1

简单地概括为规律是n! = n * (n-1)!,我们设定函数mul就是计算阶乘的;所以我们只需要返回出n * mul(n - 1)的值就可以,一直递归下去直到n == 1为止,这就是出口。

扩展(用递归求斐波那锲数列的某一项)

斐波那锲数列

1 1 2 3 5 8 13 21 34 55 ...

还是一样的,我们先找规律;上述数列中的规律就是从第二项开始,每一项都等于前面两项的和,我们定义函数fb(n)求第n项的数,规律如下:

// fb(5) ==> fb(4) + fb(3)
// fb(4) ==> fb(3) + fb(2); fb(3) ==> fb(2) + fb(1)
// fb(3) ==> fb(2) + fb(1); fb(2) ==> fb(1) + fb(0)

概率可以简单概括为:fb(n) = fb(n - 1) + fb(n - 2),我们返回出这个值就行。

我们再来找出口;我们可以看到前面两个数是没有前两项的,这就是出口,如果n为1或n为2的时候,就返回1

完整代码为:

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

这两个例子的规律还是比较好找的,但是在实际开发的过程中一些规律还是比较难找的,如果规律找到了,问题就变得没那么困难了。

数组的扁平化

什么是数组的扁平化?

数组的扁平化是将多维数组变为一维数组,数组里面不存在数组嵌套。

举个例子:将数组arr = [1, 2, [3, 4, [5]]]变为arr =[1, 2, 3, 4, 5]

方法

toString(只适用于数组里面是数字)

原理:数组的toString方法不能识别中括号,我们将得到的字符串再变成数组,就达到了效果。

let arr = [1, [2, [3]]]
let str = arr.toString() // '1,2,3'

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

console.log(newArr);

结果为:[1,2,3]

ES6中的flat

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

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

flatES6中直接提供给我们用于数组扁平化的方法,flat()括号中的参数是扁平化几次,上述代码是两次;但一般我们不知道数组是几维的,所以我们一般用Infinity

上述代码执行结果为:[1,2,3,4,5]

手写用递归扁平化数组

原理:先定义一个空数组,再遍历需要扁平化的数组,用Array.isArray(arr[i])判断下一个值是否是数组,如果是,就用递归再调用一下函数再找数组里面的数组里面的数组,如果不是数组,就往空数组里面push进去,最后返回出来结果。这个递归的出口就是循环完毕。

实现代码如下:

let arr = [1, 2, [3, 4, [5]]]
function flatten(arr) {
    //定义空数组接值
    let result = []
    //遍历数组
    for (let i = 0; i < arr.length; i++) {
        if (Array.isArray(arr[i])) {
            // flatten 就是扁平化,递归
            result = result.concat(flatten(arr[i]))  // [1, 2, 3, 4, 5]
        } else {
           //往数组里面加值
            result.push(arr[i])
        }
    }

    return result
}

console.log(flatten(arr))

上述代码执行结果为:[1,2,3,4,5]

结语

数组扁平化的方法还有一些,我们应该要熟练掌握不只一种,并且需要用得游刃有余,这样我们在面试中就不会显得那么狼狈了。最后祝大家学业有成~