『 每日一题』手写每日一题之数组扁平化

827 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第 16 天,点击查看活动详情

前一篇文章中,我们聊到面试中常见的手写题 -- 数组去重,当然除了数组去重这个考点,关于数组方面的手写题还有很多,今天我们继续来盘关于数组的另一道手写题 -- 数组扁平化

关于数组扁平化,我们先了解一下它的概念,再来看如何手写相关的代码。

简单来说:数组扁平化,就是将一个嵌套多层的数组 array (嵌套可以是任何层数)转换为只有一层的数组。

在面试中,如果遇到要将数组扁平化的题目,我们首先应该想到的就是 ES6 中提供的 flat 方法,它可以帮助我们快速的将多层嵌套数组转换为一层数组,我们来看一下 flat 的使用方法,代码如下:

function flatten(arr) {
    return arr.flat(Infinity)
}

在上面的代码中,我们可以看到在 arr 中使用 flat 方法,它有一个参数 Infinity,表示要转换的层数,当有N层要转换为一层时,而我们不知道这个N是多少时,就可以直接写 Infinity,因为使用 Infinity,可展开任意深度的嵌套数组。

当然,如果你只知道这一种方法,那肯定是不够的,如果面试官说不让用 flat 方法,让你通过其它方式来实现数组的扁平化,那该如何做呢?

我们还可以通过递归的方式来实现数组扁平化,简单来说,就是通过一个函数,内部去打平要处理的数字,并且让整个函数自己调用自己,不断的执行,最后将执行后的结果返回处理。这就是使用递归的思路,下面我们一起来看一下实现的代码:

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

function flatten(arr) {
    let result = [];
    for (let i = 0; i < arr.length; i++) {
        // 如果元素是数组,数组的结果通过数组的 concat 方法拼接到最后要返回的 result 数组
        if (Array.isArray(arr[i])) {
            result = result.concat(flatten(arr[i]));
        } else {
            result.push(arr[i]);
        }
    }
    return result;
}

通过上述代码我们可以看出,在这个函数内部,主要是通过判断当前获取的值本身是不是一个数组,如果当前获取的值还是数组,说明该值需要拍平,这样我们就继续调用该函数,直到所有的值都是数字时,就将拍平的数组返回出来。在面试中只有记得递归内部的实现原理,最重要的就是通过 Array.isArray() 来判断当前的值是否是数组,这样这个题目就算是解答出来了。

当然,光用递归来解答,大部分面试官也会算你过了,但是我们是否还能用更好的解决办法呢?

我们其实还有其它的解决办法,在 ES6 中,除了有 flat 方法能够直接扁平化数组外,我们还能借用 reduce 来实现数组的扁平化,相对 flat 来说 reduce 方法会更加的灵活,并且 reduce 方法的功能也更加强大。我们一起来看一下如何使用 reduce 实现数组扁平化,代码如下:

function flatten(arr) {
    return arr.reduce((prev, next) => {
        // 判断逻辑和递归中关键判断逻辑代码类似
        return prev.concat(Array.isArray(next) ? flatten(next) : next);
    }, []);
}

reduce 方法的参数有两个,第一个参数是一个回调函数,它又有四个可选参数,关于 reduce 的使用,我们在前面这一篇文章中有讲到过,这里使用 reduce 其实与前面的递归实现思路是差不多的,区别就在于前面的递归是需要我们自己去执行循环,在循环里面判断当前的值,而使用 reduce 则不需要我们自己去执行循环,因为 reduce 内部会帮我们完成这一步,因此使用 reduce 方法会更好一些。

其实如果你能够写到这里,这道手写题对你来说,已经算是满分通过了,但是我们还可以有其它的实现方法,这里就作为一个扩展来学习一下,当然面试中就不一定要写这么多中实现的思路了。

有一种更简单的方法,我们可以了解一下,作为一种备选的方法,只需要使用一行代码就可以实现,那么是什么方法呢?我们一起来看一下代码:

function flatten(arr) {
    return arr.toString().split(",");
}

只需要将数组 arr 转换为字符串,然后通过字符串上面的 split 方法将字符串通过逗号切割一下,就能够获取到一个一维数组了,不过一般不建议这么用,这里只是作为面试中的一种备选解题思路。

最后,我们要明白面试官出题的本意是什么,而不要为了答题而答题。毕竟还是那句话,面试是面试,工作是工作,大家一起共勉!

参考

github.com/mqyqingfeng…

segmentfault.com/a/119000004…