攤平一個多層資料陣列
什麼是攤平陣列?
攤平陣列是指將一個巢狀(多層)的陣列轉換成一個單層陣列。例如:
const nestedArray = [1, [2, 3], [4, [5, 6]]];
// 攤平後變成
// [1, 2, 3, 4, 5, 6]
我們會介紹以下幾種方法來達成這個目標:
-
使用 Array.prototype.flat() 方法(最簡單)
-
使用遞迴(recursive)方式
-
使用 reduce 方法
-
使用 concat 和展開運算符(spread operator)
方法一:使用 Array.prototype.flat()
flat() 是 JavaScript 內建的方法,專門用來攤平陣列。它簡單易用,適合大多數情況。
步驟:
-
檢查你的陣列是否為巢狀結構。
-
呼叫 flat() 方法,指定攤平的層數(預設是 1 層)。
-
如果不知道巢狀層數,可以用 Infinity 來攤平所有層級。
完整程式碼:
// 定義一個巢狀陣列
const nestedArray = [1, [2, 3], [4, [5, 6]]];
// 使用 flat() 攤平陣列
const flatArray = nestedArray.flat(Infinity);
console.log(flatArray);
// 輸出: [1, 2, 3, 4, 5, 6]
說明:
-
flat(Infinity)
會自動攤平所有層級的巢狀陣列。 -
如果只想攤平特定層數,例如只攤平一層,可以用 flat(1):
const nestedArray = [1, [2, 3], [4, [5, 6]]];
const flatOneLevel = nestedArray.flat(1);
console.log(flatOneLevel);
// 輸出: [1, 2, 3, 4, [5, 6]]
優點:
-
簡單、內建、不需要額外邏輯。
-
支援指定攤平層數。
注意事項:
- flat() 是 ES2019(ES10)引入的,確保你的環境支援(現代瀏覽器和 Node.js 版本都支援)。
方法二:使用遞迴
如果你的環境不支援 flat(),或者你想更深入理解攤平的邏輯,可以用遞迴來實現。
步驟:
-
創建一個函式,檢查每個元素是否為陣列。
-
如果是陣列,遞迴處理該陣列。
-
如果不是陣列,直接加入結果。
完整程式碼:
// 定義一個巢狀陣列
const nestedArray = [1, [2, 3], [4, [5, 6]]];
// 自訂攤平函式
function flattenArray(arr) {
// 創建一個空陣列來存放結果
const result = [];
// 遍歷陣列中的每個元素
for (let item of arr) {
// 如果元素是陣列,遞迴呼叫 flattenArray
if (Array.isArray(item)) {
result.push(...flattenArray(item));
} else {
// 如果不是陣列,直接加入結果
result.push(item);
}
}
return result;
}
// 執行攤平
const flatArray = flattenArray(nestedArray);
console.log(flatArray);
// 輸出: [1, 2, 3, 4, 5, 6]
說明:
-
Array.isArray(item)
用來檢查 item 是否為陣列。 -
如果是陣列,遞迴呼叫
flattenArray(item)
,並用展開運算符 ... 將結果加入 result。 -
如果不是陣列,直接用 push 加入 result。
優點:
-
完全自訂,適用於任何環境。
-
容易理解攤平的邏輯。
注意事項:
- 遞迴可能在非常深的巢狀陣列中導致堆疊溢出(stack overflow),但一般情況下不會有問題。
方法三:使用 reduce
reduce 是 JavaScript 中功能強大的陣列方法,可以用來攤平陣列,特別適合想用函式式程式設計(functional programming)的方式。
步驟:
-
使用 reduce 遍歷陣列。
-
檢查每個元素是否為陣列。
-
如果是陣列,遞迴攤平;如果不是,直接加入累加器(accumulator)。
完整程式碼:
// 定義一個巢狀陣列
const nestedArray = [1, [2, 3], [4, [5, 6]]];
// 使用 reduce 攤平陣列
function flattenArray(arr) {
return arr.reduce((flat, current) => {
// 如果 current 是陣列,遞迴攤平,否則直接返回 current
return flat.concat(Array.isArray(current) ? flattenArray(current) : current);
}, []);
}
// 執行攤平
const flatArray = flattenArray(nestedArray);
console.log(flatArray);
// 輸出: [1, 2, 3, 4, 5, 6]
說明:
-
reduce 的第一個參數是累加器 flat,初始值設為空陣列 []。
-
對每個元素 current,檢查是否為陣列:
-
如果是陣列,遞迴呼叫
flattenArray(current)
。 -
如果不是,直接返回 current。
-
-
使用 concat 將結果合併到累加器中。
優點:
-
程式碼簡潔,符合函式式程式設計風格。
-
邏輯清晰,容易維護。
注意事項:
-
和遞迴方法類似,深層巢狀可能導致堆疊溢出。
-
concat 的效能可能比展開運算符稍慢。
方法四:使用 concat 和展開運算符
這是一種簡單的替代方法,結合 concat 和展開運算符(...)來攤平陣列。
步驟:
-
使用 concat 和展開運算符將陣列展開。
-
如果需要多次展開,可以用迴圈或遞迴來處理多層。
完整程式碼:
// 定義一個巢狀陣列
const nestedArray = [1, [2, 3], [4, [5, 6]]];
// 使用 concat 和展開運算符攤平陣列
function flattenArray(arr) {
let result = [].concat(...arr);
// 如果結果中還有陣列,繼續遞迴攤平
while (result.some(item => Array.isArray(item))) {
result = [].concat(...result);
}
return result;
}
// 執行攤平
const flatArray = flattenArray(nestedArray);
console.log(flatArray);
// 輸出: [1, 2, 3, 4, 5, 6]
說明:
-
[].concat(...arr)
會將第一層陣列展開。 -
使用 while 迴圈檢查結果中是否還有陣列,若有則繼續展開。
-
some 方法檢查是否有元素是陣列(
Array.isArray(item))
。
優點:
-
程式碼相對簡單,易於理解。
-
不需要遞迴,適合淺層巢狀陣列。
注意事項:
-
對於非常深的巢狀陣列,效能可能不如 flat()。
-
迴圈可能導致程式碼執行時間較長。