JavaScript实现flatten多种方法

简介


我们在网上看到很多的关于数组的面试题,比如说给如下一个数组,把它拍平、去重、升序

1
let arr = [8, [5, 9, 4], 1, 3, [7, 5, 10, [3, 4, 6, 2]], 4, 3, 2, 4];

其实这个题有很多种解法,比如用 Array.prototype.flat,或者自己实现一个 flatten 函数,我们这里主要关注的时 flat 方法的实现。

第一种解法

用最新的语法

1
2
3
4
5
6
let arr = [8, [5, 9, 4], 1, 3, [7, 5, 10, [3, 4, 6, 2]], 4, 3, 2, 4];
let newArr = Array.from(new Set(arr.flat(Infinity))).sort((a, b) => {
return a - b;
});
console.log(newArr);
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

1、就是先拍平一个多维数组 arr.flat(ES6 语法)
2、再通过 Set 集合做去重
3、再通过 Array.fromSet 集合转为数组
4、再通过 sort 排序

如果不了解 flat 的函数的话,可以参考mdn Array.prototype.flat(),或者看阮一峰老师的 flat 介绍
Set 集合的讲解可以参考mdn Set,或者看阮一峰老师的 Set 介绍
我们这里主要讨论 flat 的实现。

第二种解法

1
2
3
4
5
6
7
8
9
10
let arr = [8, [5, 9, 4], 1, 3, [7, 5, 10, [3, 4, 6, 2]], 4, 3, 2, 4];
let newArr = Array.from(new Set(arr.toString().split(",")))
.map(item => {
return parseInt(item);
})
.sort((a, b) => {
return a - b;
});
console.log(newArr);
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

1、我们调用 Array 上的 toString 方法把他转换为一个字符串

1
2
arr.toString();
// "8,5,9,4,1,3,7,5,10,3,4,6,2,4,3,2,4"

这列我们就不讨论为什么返回的结果里面不包含‘[]’这两个字符串,后面我在写一篇博客来说数组,的 valueOf、toString 方法。
2、再把字符串通过 Array.prototype.split 方法转换为数组
3、再通过 Set 集合做去重
4、再通过 Array.fromSet 集合转为数组
5、再通过 sort 排序

第三种解法

自己通过封装一个 flatten,在不基于 Array.prototype.flat 方法上实现一个拍平函数

ES6 实现

1
2
3
4
5
6
7
8
let arr = [8, [5, 9, 4], 1, 3, [7, 5, 10, [3, 4, 6, 2]], 4, 3, 2, 4];
const flatten = arr =>
Array.isArray(arr) ? arr.reduce((a, b) => [...a, ...flatten(b)], []) : [arr];
let newArr = Array.from(new Set(flatten(arr))).sort((a, b) => {
return a - b;
});

// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

ES5

1
2
3
4
5
6
7
8
9
10
11
12
let arr = [8, [5, 9, 4], 1, 3, [7, 5, 10, [3, 4, 6, 2]], 4, 3, 2, 4];
function flatten(arr) {
return Array.isArray(arr)
? arr.reduce(function(prev, current) {
return [...prev, ...flatten(current)];
}, [])
: [arr];
}
let newArr = Array.from(new Set(flatten(arr))).sort((a, b) => {
return a - b;
});
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

实现思路

1、检测是否为数组
2、如果是数组,调用 reduce 函数实现合并函数
3、如果有嵌套数组,就递归调用该方法

总结

实现拍平数组大致有三种方法

  1. Array.prototype.flat 方法
  2. Array.prototype.toString 方法转为字符串,再 split
  3. 自己实现一个 flatten 函数