你能给出几种实现数组扁平化的方法?

简介: 扁平化数组没听过?那应该听说过扁平化管理吧,这可是互联网公司面试时的通用话术。简单的说,扁平化就是减少层级,可根据需要减少一个层级,或者减少到只有一个层级。扁平化数组就是将多重嵌套的数组,重新整理成一维数组。接下来就来看看可以怎么实现这种效果吧。

扁平化数组没听过?那应该听说过扁平化管理吧,这可是互联网公司面试时的通用话术。简单的说,扁平化就是减少层级,可根据需要减少一个层级,或者减少到只有一个层级。扁平化数组就是将多重嵌套的数组,重新整理成一维数组。接下来就来看看可以怎么实现这种效果吧。

思路

对于这个问题应该已经清晰明了了,如何使用js实现呢。首先我们来捋一下思路:

  • 定义一个空数组arr=[]用来表示最终返回的结果,然后遍历当前数组
  • 如果数组项是非数组类型,那么就将其添加到arr中
  • 如果是数组类型,则递归遍历后添加到arr中

思路并不复杂,主要就是判断是不是数组类型以及递归调用。

开始

使用flat

flat是数组对象新增的一个方法,可以直接调用来实现数组的深度扁平化,使用时需要传入需要扁平化的深度,默认为1,即只扁平化一层。

语法:

const newArr = arr.flat([depth])

例如:

const arr = [1,2,3,[4,5,[6]]];
console.log(arr.flat()); // [1,2,3,4,5,[6]],默认只扁平化一层

兼容性:

image-20220619214847020.png

使用for循环+递归

既然是要遍历数组,那么使用for循环最直接的选择。我们可以使用forwhileforEach来实现for循环,这次我们使用forEach,其他的也差不多。结合递归,在遍历完原数组后,需要将数组项添加到新的数组中,我们可以使用pushconcat、解构等方式来实现,这里我们选择使用push

完整代码如下:

function flatten(arr) {
    const res = [];
    arr.forEach(item => {
        if (Array.isArray(item)) {
            const flatItem = flatten(item)
            flatItem.forEach(e => res.push(e))
        } else {
            res.push(item)
        }
    })
    return res;
}
const arr = [1,2,[3,[4],5],6];
console.log(flatten(arr)); // [1,2,3,4,5,6]

上述代码也并不复杂,关键是要理解递归调用,即重复调用自身。有一点需要注意,我们判断数组项是不是数组,不能使用typeof []的方式,因为这个只能得到是object,并不确定是不是数组。因此我们可以使用Array.isArray([])或者[] instanceof Array来判断。

使用reduce+递归

除了使用for循环,我们还可以借助reduce。如果对reduce的使用还不熟悉的化,可以参考笔者之前的文章:你真的会使用reduce吗,这里我们重点讲怎么使用reduce实现数组扁平化:

const flatten = (arr) => arr.reduce((a, b) => (Array.isArray(b) ? [...a, ...flatten(b)] : [...a, b]), []);
const arr = [1,2,[3,[4],5],6];
console.log(flatten(arr)); // [1,2,3,4,5,6]

使用reduce会有一个"累加"的过程,就不用自己在调用push的方法了。而且我们使用了解构,这样代码看上去就更加简洁了。

使用toString()?不推荐

掌握一些奇淫技巧的朋友们可能会发现,对于数组直接调用toString()貌似也可以实现“扁平化”,其实这个是一个误区。数组的toString()重写了对象Object的toString()方法,结果就是把数组连接成一个字符串,这个效果和join()很像。注意返回的是一个字符串,如果原数组就是简单的字符串构成还好,如果是数字,如果是对象、Map等,那么将得不到想要的结果,或者需要进一步转换。我们来看几个例子:

const arr = ['1','2', ['3', 'a', ['b']]];
console.log(arr.toString().split(',')); // ['1','2','3','a','b'],没问题
const arr = [1,2,[3,[4],5],6];
console.log(arr.toString().split(',')); // ['1','2','3','4','5','6'],有问题,原来是数字,现在变成了字符串。需要再次转换
console.log(arr.toString().split(',').map(item => +item)); // [1,2,3,4,5,6]
const arr = [1,2,{a: 3},[4,5]];
console.log(arr.toString().split(',')); // ['1','2','object Object', '4', '5'],有问题,数据已经发生改变,且无法转换

总结

本文总结了实现数组扁平化的常用方法,每一种实现方式都不复杂,关键是要理解递归调用。在这些方法中,除了使用flat()函数,其实更推荐使用reduce来实现数组扁平化。不仅功能上满足,而且写起来代码也更加简洁。

相关文章
|
7月前
|
算法 前端开发
经典面试题:扁平化嵌套数组
经典面试题:扁平化嵌套数组
50 0
|
开发框架 .NET C#
c#数组补充
c#数组的几个简单的补充
45 0
|
7月前
|
存储 C++
定义一堆数组
定义一堆数组
91 1
|
7月前
|
存储 传感器 机器学习/深度学习
Java数组全套深入探究——进阶知识阶段6、三维数组以及更多维度数组的概念和用法
Java数组全套深入探究——进阶知识阶段6、三维数组以及更多维度数组的概念和用法
135 0
|
7月前
|
存储 Java 程序员
Java数组全套深入探究——基础知识阶段3、数组下标操作
Java数组全套深入探究——基础知识阶段3、数组下标操作
78 0
|
7月前
|
存储 Java 程序员
Java数组全套深入探究——基础知识阶段2、数组的定义语法
Java数组全套深入探究——基础知识阶段2、数组的定义语法
68 0
|
7月前
|
存储 C++
关于数组的基本要点
关于数组的基本要点
55 0
|
存储 C#
C#视频—浅谈数组与集合的差别
C#视频—浅谈数组与集合的差别
数组的三种声明方式,以及数组倒置
数组的三种声明方式,以及数组倒置
66 0
|
存储 NoSQL API
【Redi设计与实现】第六章:整数集合
【Redi设计与实现】第六章:整数集合
【Redi设计与实现】第六章:整数集合