七、JavaScript专题之数组扁平化

数组的扁平化,就是将一个嵌套多层的数组 array (嵌套可以是任何层数)转换为只有一层的数组。换句话说就是把多维数组转化成一维数组。

比如:

1
2
3
4
['a',['b',['c']]]//3 维数组
['a',['b',['c',[.....]]]]//n 维数组
// 转化为:
['a','b','c','d',...]

通常我们都会用递归的方式来实现。

递归

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var arr = [1, [2, 3], [4, [5, 6]]];

function flatten(arr) {
var result = [];
for (var i = 0; i < arr.length; i++) {
if (Array.isArray(arr[i])) {
result = result.concat(flatten(arr[i]));
// result.push(...flatten(arr[i]))
} else {
result.push(arr[i]);
}
}
return result;
}
console.log(flatten(arr));

利用 for 循环遍历数组的每一项并加以判断,如果不是数组,就执行 push 操作,是数组的化,就再次执行该函数(递归),直至遍历完整个数组。
ps: …和 concat()可以进行替换,所以完全可以算是 2 种方法。

while 循环

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

function flatten(arr) {
while (arr.some((item) => Array.isArray(item))) {
// arr = [].concat(...arr);
arr = Array.prototype.concat.apply([], arr);
console.log(arr);
}
return arr;
}
console.log(flatten(arr));

同理,利用 while 判断加上 some 的遍历来实现扁平化。

reduce 方法

1
2
3
4
5
6
7
8
var arr = [1, [2, 3], [4, [5, 6]]];

function flatten(arr) {
return arr.reduce((acc, cur) => {
return acc.concat(Array.isArray(cur) ? flatten(cur) : cur);
}, []);
}
console.log(flatten(arr));

stack 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var arr = [1, [2, 3], [4, [5, 6]]];

function flatten(arr) {
const stack = [...arr];
const result = [];
while (stack.length) {
let first = stack.shift();
if (Array.isArray(first)) {
stack.unshift(...first);
} else {
result.push(first);
}
}
return result;
}
console.log(flatten(arr));

toString

如果全是数字,可以用 toString 方法:

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

function flatten(arr) {
return arr
.toString()
.split(",")
.map((item) => +item);
}
console.log(flatten(arr));

flat

es6 提供的新方法 flat(depth),参数 depth,代表展开嵌套数组的深度,默认是 1。

1
2
3
var arr = [1, [2, 3], [4, [5, 6]]];
arr.flat(); // [1, 2, 3, 4, [5, 6]]
arr.flat(Infinity); // [1, 2, 3, 4, 5, 6]

depth 的值设置为 Infinity,无需知道数组的维度,直接将目标数组变成 1 维数组。

参考文献

https://juejin.cn/post/6844903805876699150