小知识,大挑战!本文正在参与“程序员必备小知识”创作活动
数组扁平化是一个多层嵌套的数组(多维数组)转换为只有一层的数组(一维数组)的过程。在面试过程中是一道高频热点题目,开发过程中也会偶尔使用的
现在有这么一个数组
const arr = [1, 2, [3, [4, 5]], 6, [7, 8]];
实现一个函数flatten
将其扁平化
flat
直接调用 ES6 中的 flat 方法,可以直接实现数组扁平化,这是一个官方提供的API
flat()
方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。
使用方式:
var newArray = arr.flat([depth]);
depth: 指定要提取嵌套数组的结构深度,不指定时默认值为 1。指定为Infinity
时则无论层都会扁平化为一层
arr.flat(Infinity)
⚠️:flat()
方法会移除数组中的空项
const arr = [1,,[3,4]];
arr.flat(Infinity); // [1, 3, 4]
普通递归
递归应该是最先想到的实现方式之一,递归总是可以朴实无华的解决很多问题😂
const flatten = (arr) => {
let res = [];
for (let i = 0; i < arr.length; i++) {
const item = arr[i];
if (Array.isArray(item)) {
// 如果是数组
res = res.concat(...flatten(item));
} else {
// 非数组 直接push
res.push(item);
}
}
return res;
};
上述就是通过循环递归的方式,一项一项地去遍历,如果每一项还是一个数组,那么就继续往下遍历,利用递归程序的方法,来实现数组的每一项的连接
递归 + reduce
使用reduce
来替换普通递归中冗余的判断
const flatten = (arr) => {
return arr.reduce((res, item) => {
return Array.isArray(item) ? res.concat(...flatten(item)) : res.concat(item)
}, []);
};
代码整体简洁很多,简化了for
循环和if
条件判断,但是整体思路和简单递归保持一致
while + some
const flatten = (arr) => {
while (arr.some((item) => Array.isArray(item))) {
arr = [].concat(...arr);
}
return arr;
};
整体思路:通过while
进行不断循环,结束条件为整个数组变成一维数组,只要存在多维数组则循环条件就一直成立
some
函数用于检测是否存在多维数组
while
内部用于不断的一层一层扁平化数据
整个while
循环结束,数组就是我们想要的一维数组
while + 堆栈
核心流程参考代码中注释
const flatten = (arr) => {
const stack = [...arr];
const res = [];
while (stack.length) {
// 使用 pop 从 stack 中取出并移除值
const next = stack.pop();
if (Array.isArray(next)) {
// 使用 push 送回内层数组中的元素,不会改动原始输入
stack.push(...next);
} else {
res.push(next);
}
}
// 反转恢复原数组的顺序
return res.reverse();
};
toString + split
将数组toString
const str = arr.toString(); // 1,2,3,4,5,32,6,7,8
将得到的字符串split
分割为数组,以,
分割
str.split(','); // ['1', '2', '3', '4', '5', '32', '6', '7', '8']
简历的两个API便可以实现数组扁平化
Generator
利用Generator
特性实现
const flatten = function* (arr) {
for (const item of arr) {
if (Array.isArray(item)) {
yield* flatten(item);
} else {
yield item;
}
}
};
console.log([...flatten(arr)]);
Reg + JSON
const flatten = (arr) => {
let str = JSON.stringify(arr);
str = str.replace(/(\[|\])/g, '');
str = '[' + str + ']';
return JSON.parse(str);
};
整体思路:
- 首先将数组序列化,得到一个字符串
- 利用正则将序列化后的字符串中的
[
和]
全部替换 - 手动拼接
[]
,将其反序列化之后便是扁平化后的数组