Skip to main content

攤平一個多層資料陣列

什麼是攤平陣列?

攤平陣列是指將一個巢狀(多層)的陣列轉換成一個單層陣列。例如:

const nestedArray = [1, [2, 3], [4, [5, 6]]];
// 攤平後變成
// [1, 2, 3, 4, 5, 6]

我們會介紹以下幾種方法來達成這個目標:

  1. 使用 Array.prototype.flat() 方法(最簡單)

  2. 使用遞迴(recursive)方式

  3. 使用 reduce 方法

  4. 使用 concat 和展開運算符(spread operator)


方法一:使用 Array.prototype.flat()

flat() 是 JavaScript 內建的方法,專門用來攤平陣列。它簡單易用,適合大多數情況。

步驟:

  1. 檢查你的陣列是否為巢狀結構。

  2. 呼叫 flat() 方法,指定攤平的層數(預設是 1 層)。

  3. 如果不知道巢狀層數,可以用 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(),或者你想更深入理解攤平的邏輯,可以用遞迴來實現。

步驟:

  1. 創建一個函式,檢查每個元素是否為陣列。

  2. 如果是陣列,遞迴處理該陣列。

  3. 如果不是陣列,直接加入結果。

完整程式碼:

// 定義一個巢狀陣列
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)的方式。

步驟:

  1. 使用 reduce 遍歷陣列。

  2. 檢查每個元素是否為陣列。

  3. 如果是陣列,遞迴攤平;如果不是,直接加入累加器(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 和展開運算符(...)來攤平陣列。

步驟:

  1. 使用 concat 和展開運算符將陣列展開。

  2. 如果需要多次展開,可以用迴圈或遞迴來處理多層。

完整程式碼:

// 定義一個巢狀陣列
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()。

  • 迴圈可能導致程式碼執行時間較長。