請實踐陣列扁平化 (flatten)
2022年12月30日
💎 加入 E+ 成長計畫 如果你喜歡我們的內容,歡迎加入 E+,獲得更多深入的軟體前後端內容
陣列扁平化指的是將超過一維的陣列轉化為只有一維的陣列,目前社群中有許多效用函式庫有提供這個方法,例如知名的 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]