Merge/flatten an array of arrays

Merge/flatten an array of arrays

技术背景

在 JavaScript 开发中,经常会遇到需要将嵌套数组扁平化的需求,即将多维数组转换为一维数组。例如,从服务器获取的数据可能是多层嵌套的数组结构,而我们在处理时需要将其扁平化以便后续操作。

实现步骤

ES2019 方法

ES2019 引入了 Array.prototype.flat() 方法来扁平化数组:

1
2
3
4
5
6
7
8
9
10
11
const arrays = [
["$6"],
["$12"],
["$25"],
["$25"],
["$18"],
["$22"],
["$10"]
];
const merge3 = arrays.flat(1); // 深度指定嵌套数组结构应扁平化的级别,默认为 1
console.log(merge3);

支持多层嵌套扁平化,传入 Infinity 可扁平化所有层级:

1
2
const arr4 = [2, 2, 5, [5, [5, [6]], 7]];
arr4.flat(Infinity); // [2, 2, 5, 5, 5, 6, 7]

兼容旧浏览器的方法

  • 使用 Array.prototype.concat
1
2
3
4
5
6
7
8
9
10
11
var arrays = [
["$6"],
["$12"],
["$25"],
["$25"],
["$18"],
["$22"],
["$10"]
];
var merged = [].concat.apply([], arrays);
console.log(merged);
  • 递归方法:
1
2
3
4
5
6
function flatten(arr) {
return arr.reduce(function (flat, toFlatten) {
return flat.concat(Array.isArray(toFlatten) ? flatten(toFlatten) : toFlatten);
}, []);
}
console.log(flatten([[1, 2, 3], [4, 5]])); // [1, 2, 3, 4, 5]

其他方法

  • 使用 join()split()
1
2
3
4
5
6
7
8
9
10
11
let arrs = [
["$6"],
["$12"],
["$25"],
["$25"],
["$18"],
["$22"],
["$10"]
];
let newArr = arrs.join(",").split(",");
console.log(newArr);

但如果字符串包含逗号,此方法会有问题。

  • 使用生成器函数:
1
2
3
4
5
function* flatten(arr) {
if (!Array.isArray(arr)) yield arr;
else for (let el of arr) yield* flatten(el);
}
console.log(...flatten([1,[2,[3,[4]]]])); // 1 2 3 4

最佳实践

  • 如果支持 ES2019,优先使用 Array.prototype.flat() 方法,因为它简洁且性能较好。
  • 处理大型数组时,要避免使用 Function.prototype.apply 或扩展运算符,因为可能会导致栈溢出。可以使用栈安全的实现方式。
  • 如果需要兼容旧浏览器,可以使用递归或 Array.prototype.concat 方法。

常见问题

  • Array.prototype.flat() 兼容性问题: 该方法较新,在旧浏览器(如 Internet Explorer)中不可用。可以使用 Babel 等工具进行转换,或者使用兼容的实现方法。
  • 栈溢出问题: 对于大型数组,如果使用 [].concat.apply([], arrays) 或扩展运算符 [].concat(...arrays) 可能导致栈溢出。需要使用栈安全的实现。
  • 字符串包含逗号问题: 使用 join()split() 方法时,如果数组元素是包含逗号的字符串,会导致结果不符合预期。需避免使用此方法或采用其他处理方式。

Merge/flatten an array of arrays
https://119291.xyz/posts/merge-flatten-an-array-of-arrays/
作者
ww
发布于
2025年5月30日
许可协议