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

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

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

首先我们先了解一下数组扁平化的应用场景,数组扁平化一般在一些多维数组的应用中会出现,因为操作多维数组会较为麻烦,因此将多维数组扁平化变为一维数组后,将大大简化我们对数组的操作,这一节我们就一起来学习一下关于数组扁平化的 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

相关推荐

indexOf的三种使用方法

indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置。这里基本用法大家一般都清楚,一般在实际工作中常与数组的方法合用来对数组进行一些操作

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

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

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

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

js数组中改变元素的位置:互换,置顶,上移,下移

unshift() 方法可向数组的开头添加一个或更多元素,并返回新的长度。shift() 方法用于把数组的第一个元素从其中删除,并返回第一个元素的值。splice() 方法可删除从 index 处开始的零个或多个元素

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

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

Js遍历数组时注意 Empty Item 的影响

这两天碰到个问题:从日志中发现一些来自 iOS 10.3 的报错「Cannot read property \\\'xxx\\\' of undefined」,定位到代码的报错位置,发现是遍历某数组时产生的报错,该数组的元素应该全都是 Object,但实际上出现了异常的元素

JS数组扁平化(flat)方法总结

需求:多维数组=>一维数组 ;flat和flatMap方法为ES2019(ES10)方法,目前还未在所有浏览器完全兼容。第四种处理:用 reduce 实现数组的 flat 方法

数组、字符串去重

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

Js数组中所有方法(超详细)

concat()把元素衔接到数组中。 every() 方法使用指定函数检测数组中的所有元素:filter()返回满足断言函数的数组元素。forEach()为数组的每一个元素调用指定函数。

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

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

点击更多...

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