问题:如何实现数组扁平化?
数组扁平化是将多维数组转换为一维数组的过程,本文汇总多种实现方案及适用场景。
核心方案
| 方法 | 时间复杂度 | 空间复杂度 | 特点 |
|---|---|---|---|
| flat() | O(n) | O(n) | 最简洁,ES2019 |
| reduce | O(n²) | O(n) | 兼容性好 |
| while + concat | O(n²) | O(n) | 手动控制深度 |
| toString + split | O(n) | O(n) | 简单但不优雅 |
具体实现
1. flat()(推荐)
时间复杂度:O(n) | 空间复杂度:O(n)
// 扁平一层
[1, [2, 3]].flat(); // [1, 2, 3]
// 扁平所有层级
[1, [2, [3, [4]]]].flat(Infinity); // [1, 2, 3, 4]
// 兼容写法
const flatten = arr => arr.flat ? arr.flat(Infinity) : arr;原理:ES2019 原生方法,参数为扁平层级
2. reduce
时间复杂度:O(n²) | 空间复杂度:O(n)
// 扁平指定层级
function flatten(arr, depth = Infinity) {
return depth > 0
? arr.reduce((prev, cur) => {
return prev.concat(Array.isArray(cur) ? flatten(cur, depth - 1) : cur);
}, [])
: arr;
}
// 使用
flatten([1, [2, [3, [4]]]]); // [1, 2, 3, 4]原理:递归拼接数组元素
3. while + concat
时间复杂度:O(n²) | 空间复杂度:O(n)
function flatten(arr) {
while (arr.some(item => Array.isArray(item))) {
arr = arr.concat(...arr);
}
return arr;
}
// 使用
flatten([1, [2, [3, [4]]]]); // [1, 2, 3, 4]原理:循环检查是否存在数组,逐层展开
4. toString + split
时间复杂度:O(n) | 空间复杂度:O(n)
function flatten(arr) {
return arr.toString().split(',').map(Number);
}
// 使用
flatten([1, [2, [3, [4]]]]); // [1, 2, 3, 4]原理:转字符串再分割(仅适合纯数字数组)
方案对比
| 方案 | 优点 | 缺点 |
|---|---|---|
| flat() | 代码简洁,性能好 | 需要 ES2019+ |
| reduce | 兼容性好,可控深度 | 代码稍复杂 |
| while+concat | 无需指定深度 | 性能较差 |
| toString | 极简 | 只能处理数字,会改变类型 |
面试追问
Q:如何实现深度限制的扁平化?
// 扁平2层
[1, [2, [3]]].flat(2); // [1, 2, [3]]Q:如何手写 flat() polyfill?
function flat(arr, depth = 1) {
if (depth <= 0) return arr;
return arr.reduce((prev, cur) => {
return prev.concat(Array.isArray(cur) ? flat(cur, depth - 1) : cur);
}, []);
}知识图谱
- 父级概念:算法与数据结构
- 关联概念:
- 如何实现数组去重? — 数组操作相关
- JavaScript — 实现语言
- 时间复杂度 — 方案选择依据
参考延伸
- MDN: Array.prototype.flat()
- LeetCode 344. Reverse String(数组操作相关)