前端练习22 数组展平

展平数组的几种方法。

知识点

  1. concat方法可以接受数组作为参数,也可以接受非数组成员作为对象
  2. 递归
  3. reduce方法
  4. 判断数组类型
  5. flat方法

题目

编写一个JavaScript函数,接受一个仅包含数字的多维数组,返回拍平以后的结果。例如传入:[1, [2, [3, [4], 5], 6], 7],返回[1, 2, 3, 4, 5,6,7]

实现1

明显要通过递归实现,可以使用reduce方法,它可以保存当前只执行过的结果在total中,如果当前项目current仍然是数组,那么需要将递归执行的结果与total拼接

1
2
3
4
5
6
const flatDeep = (arr) => {
if (!Array.isArray(arr) || arr.length === 0) {
return [];
}
return arr.reduce((total, current) => total.concat(Array.isArray(current) ? flatDeep(current) : current), [])
};

实现2

可以不使用reduce方法,通过递归实现,构造一个闭包,通过闭包中的变量来传递结果

1
2
3
4
5
6
7
8
9
10
11
12
13
function flatDeep2(arr) {
const result = [];
(function _flat(array) {
array.forEach(v => {
if (Array.isArray(v)) {
_flat(v)
} else {
result.push(v);
}
})
})(arr);
return result;
}

实现3

也可以不使用递归,直接使用循环实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// ES6
function flatDeep3_1(arr) {
const stack = [...arr];
const result = [];
while (stack.length > 0) {
const target = stack.pop();
if (Array.isArray(target)) {
stack.push(...target);
} else {
result.unshift(target);
}
}
return result;
}

// ES5
function flatDeep3_2(arr) {
const stack = [].concat(arr);
const result = [];
while (stack.length > 0) {
const target = stack.pop();
if (Object.prototype.toString.call(target) === '[object Array]') {
[].push.apply(stack, target);
} else {
result.unshift(target);
}
}
return result;
}

实现4

还可以利用Generator实现:

1
2
3
4
5
6
7
8
9
10
11
12
function flatDeep4(arr) {
function* _flatDeep(array) {
for (const current of array) {
if (Array.isArray(current)) {
yield* _flatDeep(current);
} else {
yield current
}
}
}
return [..._flatDeep(arr)];
}

实现5

不考虑兼容性,还可以直接使用Array.prototype.flat(depth)方法,其中depth是要展开的深度,默认是1,传入Infinity作为深度,可以展开任意深度的嵌套数组。

要注意的是,flat()方法会移除数组中的空项

1
2
3
function flatDeep5(arr) {
return arr.flat(Infinity);
}

参考