请实践数组扁平化 (flatten)
2022年12月30日
💎 加入 E+ 成長計畫 與超過 500+ 位軟體工程師一同在社群中成長,並且獲得更多的軟體工程學習資源
数组扁平化指的是将超过一维的数组转化为只有一维的数组,目前社群中有许多效用函式库有提供这个方法,例如知名的 lodash 函式库就有flattenDeep
方法来协助转换数组。实际例子如下,不管有几层,通过 flattenDeep
后都会被转换成一维数组:
let array = [1, 2, [3, [4, 5, [6, 7, [8]]]]];
function flattenDeep(arr) {
...
}
const flattenArray = flattenDeep(array);
console.log(flattenArray); // [1,2,3,4,5,6,7,8]
在前端的白板面试中,很常会出现「假如没有现成的函式库,你会怎么实践数组扁平化?」的问题。假如你还不知道要如何实践的话,本篇文章会提出几种方法,让我们一起来看看吧。
方法一:flat()
其实不用透过函式库,现在要实践数组扁平化,最简单的方法是透过 JavaScript 的原生方法 — Array.prototype.flat()。
flat()
方法会接受一个参数 depth,这个 depth 参数代表要扁平化的维度,如果没有传入任何值,预设值会是 1,最后此方法会回传一个新数组。要注意的一点,flat()
方法在扁平化时会忽略空格,可以看以下代码:
// array 是一个五维数组
let array = [1, 2, , [3, [4, 5, [6, 7, [8]]]]];
// depth 传入 2,最后会去除空格,结果回传一个 3 维数组
console.log(array.flat(2)); // [1,2,3,4,5,[6, 7, [8]]
以上方法看起来很方便,但如果不知道深度是多少,也无法做到完全扁平化。所以要如何在不知道数组是多少维度的情况下做到扁平化?其实只要将 depth 的参数传入 Infinity
就可以完成。
let array = [1, 2, [3, [4, 5, [6, 7, [8]]]]];
function flatten(arr) {
return arr.flat(Infinity);
}
const flattenArray = flatten(array);
console.log(flattenArray); // [1,2,3,4,5,6,7,8]
方法二:透过递回的方式实践
当然,面试官可能会追问「如果不用原生方法,你要如何自己实践一个 flatten
?」。此时可以透过递回的方式来实践。透过 for 回圈检查数组中每一个项目,如果该项目是数组,就继续呼叫 flatten
函式;若非数组,那就直接透过 push
方法加进新数组中。
let array = [1, 2, [3, [4, 5, [6, 7, [8]]]]];
function flatten(arr, output = []) {
for (const val of arr) {
if (Array.isArray(val)) {
flatten(val, output);
} else {
output.push(val);
}
}
return output;
}
const flattenArray = flatten(array);
console.log(flattenArray); // [1,2,3,4,5,6,7,8]
方法三:reduce
使用 reduce
去递回每一层数组,并组成一个新数组。方法三和方法二的逻辑类似,只是在方法三透过 reduce
简化 for 回圈的写法。
let array = [1, 2, [3, [4, 5, [6, 7, [8]]]]];
function flatten(arr) {
return arr.reduce(
(acc, cur) =>
// 判断目前 cur 是否为数组,如果是数组,则将递回地对该元素呼叫 flatten
// 如果不是数组,就直接加入到新数组的最后一位
Array.isArray(cur) ? [...acc, ...flatten(cur)] : [...acc, cur],
[]
);
}
const flattenArray = flatten(array);
console.log(flattenArray); // [1,2,3,4,5,6,7,8]