实现数组扁平化的六种方式

更新日期: 2022-09-03阅读: 826标签: 数组

在日常的开发中,我们经常会需要将数组做扁平化处理,以方便我们的开发,那么如何实现数组扁平化呢?

首先我们先了解一下数组扁平化的应用场景,数组扁平化一般在一些多维数组的应用中会出现,因为操作多维数组会较为麻烦,因此将多维数组扁平化变为一维数组后,将大大简化我们对数组的操作,这一节我们就一起来学习一下关于数组扁平化的 6 种方式吧!

先思考

首先,我们还是先带着问题来学习,问题如下:

  • 如何通过最普通的方法来解决数组扁平化问题?
  • ES6 中是否有一些高级的方法能够直接实现数组扁平化?


数组扁平化

上面说了这么多,还没有介绍 数组扁平化 是什么?数组的 扁平化 其实就是将一个多层嵌套的数组转换为只有一层的数组,我们可以通过一个例子来看一下,代码如下:

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

// 伪代码
console.log(flatten(arr)); // [1, 2, 3, 4, 5]

上述代码中,我们通过 flatten 方法将多维数组转换为一维数组,这个方法就是数组扁平化,那么该如何实现 flatten 呢?下面我们实现一下。


普通递归实现

通过循环递归的方法,一项一项的去遍历,如果数组中的每一项都还是一个数组,那么就继续遍历下去。利用递归调用的方法,来实现数组中的每一项的连接,让我们一起来看一下代码,如下:

// 递归调用
const arr = [1, [2, [3, 4, 5]]];

const flatten = (arr) => {
    let result = [];
    
    for (let i = 0; i < arr.length; i++) {
        if (Array.isArray(arr[i])) {
            result = result.concat(flatten(arr[i]));
        } else {
            result.push(arr[i]);
        }
    }
    return result;
};

flatten(arr); // [1, 2, 3, 4, 5]

上述代码中,通过循环遍历数组,判断数组中的每一项是否是数组,如果当前元素不是数组,则直接添加到一个临时存储的空数组中,然后通过递归不断来执行这个数组,直到数组中的所有元素都执行完毕,则会返回整个扁平化后的数组。


利用 reduce 函数迭代

通过上面的普通递归函数可以发现,其实就是对数组中的每一项进行处理,这跟前面一节中说的 reduce 来实现数组的拼接很类似,因此这里我们可以使用 reduce 来实现函数迭代,从而简化第一种方法,具体的代码如下:

// reduce 函数
const arr = [1, [2, [3, 4, 5]]];

const flatten = (arr) => {
    return arr.reduce((prev, next) => {
        return prev.concat(Array.isArray(next) ? flatten(next) : next)
    }, []);
};

console.log(flatten(arr)); // [1, 2, 3, 4, 5]

上面的代码中,通过 reduce 来遍历数组,其内部还是判断每一项是否是一个数组,如果不是就累加,否则就继续执行 flatten,其实思路跟第一种的递归的一样的,只是实现起来相对简单一些。


扩展运算符实现

在上面我们通过 reduce 方法来实现数组扁平化,那么是否还有更简单的办法呢?答案是有的,那就是使用 扩展运算符实现 ,我们一起来看一下具体的实现代码,如下:

// 扩展运算符
const arr = [1, [2, [3, 4, 5]]];

const flatten = (arr) => {
    while (arr.some(item => Array.isArray(item))) {
        arr = [].concat(...arr);
    }
    return arr;
};

console.log(flatten(arr)); // [1, 2, 3, 4, 5]

在上面的方法中,通过 while 循环,判断每一项是否是数组,如果是就执行 while 循环内部的语句,通过 扩展运算符 将每一项不是数组的内容添加到数组中,最后当 while 条件不成立时,就代表数组中的每一项都已经被拍平了。

上面的三种实现数组扁平化的方式都是最基本的思路,都是通过最普通的递归思路衍生的方法来实现的,尤其是前两种比较类似,值得注意的是 reduce 方法,它可以在很多场景中应用实现。由于 reduce 方法提供的几个参数比较灵活,能够解决很多问题,因此是值得我们熟练掌握并精通的一个方法。

那么除了上面的三种方法,是否还有其他的实现思路呢?让我们接着往下看。


使用 split 和 toString 共同处理

由于数组默认带有一个 toString 的方法,因此我们可以将数组转换为带逗号的字符串,然后再使用数字的 split 方法将字符串进行切割,具体的代码如下:

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

const flatten = (arr) => {
    return arr.toString().split(',');
};

console.log(flatten(arr)); // ['1', '2', '3', '4', '5']

通过 toString 和 split 对数组进行转换和切割后,最后将数组打平,但是数组中的数字变成了字符串,因此这种方法其实是有一定的破坏性,它会将数组中的数据类型进行修改。


ES6 中的 flat

除了上述通过 toString 和 split 对数组进行处理外,我们还可以直接使用 ES6 中新增的 flat 方法来实现数组的扁平化,先看一下 flat 的使用语法:arr.flat([depth]),其中 depth 是代表数组可以展开的深度,也就是可以展开几层数组。展开的层数是根据 depth 决定的,如果是多层的话,只需要传入 Infinity ,代表无论是多少层都会展开,下面我们一起来看一下用 flat 怎么实现数组扁平化,代码如下:

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

const flatten = (arr) => {
    return arr.flat(Infinity)
};

console.log(flatten(arr)); // [1, 2, 3, 4, 5]

上面的代码中,我们在 flat 内部设置的参数是 Infinity,其实也可以传入一个 3,因此数组的层数是3层,因此 flat 的参数其实也可以是数组本身的层数,如果我们不知道数组有多少层,那么使用 Infinity 就可以了。


使用正则和 JSON 方法共同处理

除了上面说的这些方法外,我们还可以通过正则和 JSON 中的 stringify 来做数组扁平化,让我们一起来看代码,如下:

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

const flatten = (arr) => {
    let str = JSON.stringify(arr);
    str = str.replace(/(\[|\])/g, '');
    str = '[' + str + ']';
    return JSON.parse(str);
};

console.log(flatten(arr)); // [1, 2, 3, 4, 5]

在上述的代码中,我们首先通过 JSON.stringify 将数组转换为字符串,然后通过正则表达式将数组中的方括号过滤掉,最后将替换后的字符串通过 JSON.parse 方法转换为数组。

以上就实现了6中数组扁平化的方法,你还能想出其它的解决方案吗?


最后

在这篇文章中,我们学习了常见的6种数组扁平化的方法,在实际开发中我们可以运用这篇文章中讲到的知识点来将多维数组转换为一维数组,这样操作起来会更加的简便。当然,日常开发中不可能是存储的数组,有时候也是多层的数组对象,那么遇到数组对象我们该如何做数组的扁平化呢?这个问题你可以自己思考一下。

我们学完这6种方法后,那么最前面的两个问题,你现在知道该如何解答了吧!

作者:爱吃鱼的桶哥Z
链接:https://juejin.cn/post/7137308369886380040

链接: https://fly63.com/article/detial/12071

探索JavaScript数组奥秘

avaScript数组同后端语言一样,具有它自己的数据结构,归根结底,这种数据结构,本质就是一种集合。在后端语言中(如java,.net等),数组是这样定义的:数组是用来存储相同数据类型的集合

js使用数组+循环+条件实现数字转换为汉字的简单方法。

单个数字转汉字的解决方法:利用数组存储0-9的汉字、 ary.length和str.length不用多说,这是指ary数组和str字符串的长度。这里我们需要注意的是str.charAt(j)和ary[i],分别指在str这个字符串中索引为j的元素,在ary中索引为i的元素。

[译]async-await 数组循环的几个坑

在 Javascript 循环中使用 async/ await 循环遍历数组似乎很简单,但是在将两者结合使用时需要注意一些非直观的行为。让我们看看三个不同的例子,看看你应该注意什么,以及哪个循环最适合特定用例。

数组、字符串去重

今天说的数组和字符串去重呢,主要用到es6新的数据结构 Set,它类似于数组,但是成员的值都是唯一的,没有重复的值,所以活用Set来进行数组和字符串的去重。

JavaScript 数组方法

数组方法:1、Array.join([param]) 方法:将数组中所有的元素都转换为字符串并连接起来,通过字符 param 连接,默认使用逗号,返回最后生成的字符串2、Array.reverse() 方法:将数组中的元素颠倒顺序(在原数组中重新排列它们),返回逆序数组

如何删除JavaScript 数组中的虚值

falsy(虚值)是在 Boolean 上下文中已认定可转换为‘假‘的值.JavaScript 在需要用到布尔类型值的上下文中使用强制类型转换(Type Conversion )将值转换为布尔值,比如:在条件语句或者循环语句中。

JavaScript中十种一步拷贝数组的方法

JavaScript中我们经常会遇到拷贝数组的场景,但是都有哪些方式能够来实现呢,我们不妨来梳理一下。扩展运算符(浅拷贝)自从ES6出现以来,这已经成为最流行的方法。

JS数组的几个经典api

本文主要来讲数组api的一些操作,如简单实现扁平化n维数组、数组去重、求数组最大值、数组求和、排序、对象和数组的转化等。扁平化嵌套数组/展平和阵列孔——flat()

关于Vue不能监听(watch)数组变化

vue无法监听数组变化的情况,但是数组在下面两种情况下无法监听:利用索引直接设置数组项时,例如arr[indexofitem]=newValue;修改数组的长度时,例如arr.length=newLength

JS计算两个数组的交集、差集、并集、补集(多种实现方式)

使用 ES5 语法来实现虽然会麻烦些,但兼容性最好,不用考虑浏览器 JavaScript 版本,使用 ES5 语法来实现虽然会麻烦些,但兼容性最好,不用考虑浏览器 JavaScript 版本。也不用引入其他第三方库。

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!