JavaScript专题之八:数组扁平化


本文摘自PHP中文网,作者coldplay.xixi,侵删。

目录

  • 一、递归
  • 二、reduce
  • 三、apply+some
  • 四、ES6展开运算符
  • 五、toString
  • 六、正则
  • 七、实现自己的扁平化工具方法
  • 写在最后

(免费学习推荐:javascript视频教程

一、递归

for循环是我们在进行数组操作时最容易想到的,在不考虑时间和空间复杂度的时候,递归应该是一个完美的选择!

示例:

1

2

3

4

输入

const arr = [1, [2, [3, 4, { a: 1 }], null], undefined];`

输出

[ 1, 2, 3, 4, { a: 1 }, null, undefined ]

代码:

1

2

3

4

5

6

7

8

9

10

11

function flatten(arr) {

    let res = [];

    for (let i = 0; i < arr.length; i++) {

        if (Array.isArray(arr[i])) {

            // 因为函数返回的是数组,所以要做拼接处理

            res = res.concat(flatten(arr[i]));

        } else {

            res.push(arr[i])

        }

    }

    return res;}

注意:

  1. 判断数组内元素的基本类型
  2. 如果不是数组:直接存入新数组中
  3. 如果是数组:重复第一步,直到将最后一个不是数组的元素存入到新数组中

二、reduce

先来看看reduce是做什么的:reduce() 方法对数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其结果汇总为单个返回值。

示例:

1

2

3

4

输入

const arr = [1, [2, [3, 4, { a: 1 }], null], undefined];`

输出

[ 1, 2, 3, 4, { a: 1 }, null, undefined ]

代码:

1

2

3

4

5

6

function flatten(arr) {

    return arr.reduce((prev, next) => {

        // prev表示上一次操作的结果

        return prev.concat(Array.isArray(next) ? flatten(next) : next)

    }, [])

    // 注意reduce的初始值应该是[],否则无法进行拼接}

注意:

仔细对照方法一方法二,两者思路完全一致――找到数据类型是数组的子元素,对其进行抹平处理,只不过实现的细节略有不同。

唯一需要注意的地方就是拼接时数据的基本类型要以数组开始。

三、apply+some

既然方法二是方法一的变式,那个方法三也可以说是方法二的变式,但不在采用递归的方式,而是一层一层“拆除”嵌套的方式

先来看看用到的API:

  • apply:调用一个具有给定this值的函数,以及以一个数组(或类数组对象)的形式提供的参数。
  • some:测试数组中是不是至少有1个元素通过了被提供的函数测试。它返回的是一个Boolean类型的值

代码:

1

2

3

4

5

6

function flatten(arr) {

    while (arr.some(item => Array.isArray(item))) {

        // 只要存在数组类型的元素,就抹平一层

        arr = [].concat.apply([], arr)

    }

    return arr;}

注意:

大家疑惑的点主要在apply,其实主要目的就是减少括号

1

let res = [];res  = res.concat({});// 等价于[].concat.apply([], [{}])

在本例中:

1

arr = [].concat.apply([], arr);// 等价于[].concat(1, [2, [3, 4, { a: 1 }], null], undefined)

四、ES6展开运算符

大家可能业也注意到了,方法一到方法三 我们不断的借助现有方法,以精简我们的代码量,本方法也是如此~

我们利用ES6的展开运算符(用于取出参数对象的所有可遍历属性,拷贝到当前对象之中),继续精简方法三:

代码:

1

2

3

4

5

6

function flatten(arr) {

    while (arr.some(item => Array.isArray(item))) {

        // 只要存在数组类型的元素,就抹平一层

        arr = [].concat(...arr)

    }

    return arr;}

五、toString

如果前面四个方法是我们可以实现的主流的方式,那么接下来的几个就是我们可以实现的“非主流”方式,直接上代码!

1

2

3

function flatten(arr) {

    return arr.toString().split(',').map(function(item){

        return +item    })}

注意:

将数据转换类型存在类型的限制,如果原始数据是这样的:[1, ‘2’],那么就会出现问题

六、正则

假如我们默认了类型会被转换这一缺陷,那么还可以通过更暴力里的方式来将数组扁平化:

1

2

function flatten(arr) {

    return JSON.stringify(arr).replace(/\[|\]/g, '').split(',');}

注意:

如果是纯数组,貌似没什么问题

1

2

function flatten(arr) {

    return JSON.parse('[' + JSON.stringify(arr).replace(/\[|\]/g, '').split(',') + ']')}

但如果数组内存在对象,就需要消除JSON后的后果,这样更严谨一些~

到这里,六种方法算是包括了大部分数组扁平化的实现,那么如果希望将我们的方法“升级”成工具怎么办?这时候我们就要“抄袭”一下loadsh了~

七、实现自己的扁平化工具方法

这里我们简化了loadsh里的flatten函数,具体改动我们来看代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

/*

* @private

* @param {Array} array 需要扁平化的数组

* @param {number} depth 最多处理几层

* @param {boolean} [isStrict] 是否严格处理函数

* @param {Array} [result=[]] 输出的数组

* @returns {Array}

*/function flatten(array, depth, isStrict, result) {

   result || (result = [])

   // 边界

   if (array == null) return result;

 

   for (const value of array) {

       if (depth > 0 && Array.isArray(value)) {

           if (depth > 1) {

               flatten(value, depth - 1, isStrict, result)

           } else {

               result.push(...value); // 只拆1层

           }

       } else if (!isStrict) {

           result[result.length] = value        }

   }

   return result;}

  1. 该方法提供了扁平化层数

1

const res = flatten([1, 2, [3, 4, [5, 6]], { a: 1 }, null, undefined], 1, false);// [ 1, 2, 3, 4, [ 5, 6 ], { a: 1 }, null, undefined ]

  1. 该方法提供了扁平化后相反的效果

1

const res = flatten([1, 2, [3, 4, [5, 6]], { a: 1 }, null, undefined], 1, true);// [ 3, 4, [ 5, 6 ] ]const res = flatten([1, 2, [3, 4, [5, 6]], { a: 1 }, null, undefined], 2, true);// [ 5, 6 ]

isStrict参数打开后,扁平后保留了被暴漏出来的元素,剔除了浅层元素。

写到这里我们即了解了扁平化的处理思路,也有了一定的实现能力,如果你能完全理解上面的代码,相信扁平化这一部分应该难不到你了,我们下一篇文章继续研究loadsh的另一个方法~

相关免费学习推荐:javascript(视频)

以上就是JavaScript专题之八:数组扁平化的详细内容,更多文章请关注木庄网络博客

相关阅读 >>

javascript与php的区别是什么

c和javascript的区别是什么

javascript中的注释如何使用

javascript怎么删除元素属性

html5中的script属性及js同步和异步加载实现代码详解

angularjs“路由”的简介及用法介绍

javascript类型判断的方法介绍(代码示例)

javascript中字母如何转为数字

javascript url怎么隐藏

javascript是js吗

更多相关阅读请进入《javascript》频道 >>




打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

评论

管理员已关闭评论功能...