JavaScript Object.groupBy() 與 Map.groupBy()

在處理資料陣列時,我們經常需要根據某個屬性(如:類別、狀態、年份)對資料進行「分組」(Grouping)。

在 ES2024 之前,我們通常必須自己寫 reduce()forEach() 來手動建立一個物件或 Map 來存放分組後的資料。現在,JavaScript 內建了 Object.groupBy()Map.groupBy() 讓這件事變得異常簡單。

Object.groupBy()

Object.groupBy() 會回傳一個普通的 JavaScript 物件,物件的鍵 (Key) 是分組的標籤,值 (Value) 是該分組對應的元素陣列。

範例:依類別分類水果

const inventory = [
  { name: 'asparagus', type: 'vegetables', quantity: 5 },
  { name: 'bananas', type: 'fruit', quantity: 0 },
  { name: 'goat', type: 'meat', quantity: 23 },
  { name: 'cherries', type: 'fruit', quantity: 5 },
  { name: 'fish', type: 'meat', quantity: 22 },
];

const result = Object.groupBy(inventory, ({ type }) => type);

/* 輸出結果:
{
  vegetables: [
    { name: "asparagus", type: "vegetables", quantity: 5 }
  ],
  fruit: [
    { name: "bananas", type: "fruit", quantity: 0 },
    { name: "cherries", type: "fruit", quantity: 5 }
  ],
  meat: [
    { name: "goat", type: "meat", quantity: 23 },
    { name: "fish", type: "meat", quantity: 22 }
  ]
}
*/

Map.groupBy()

Map.groupBy() 的運作方式與 Object.groupBy() 幾乎一模一樣,但它回傳的是一個 Map 物件。

這在你需要使用「非字串」作為鍵(例如使用物件作為 Key)的時候非常有用。

範例:依庫存狀態分類

const stockStatus = { ok: '庫存充足', low: '庫存低' };

const inventory = [
  { name: 'Item A', quantity: 10 },
  { name: 'Item B', quantity: 2 },
  { name: 'Item C', quantity: 15 },
];

const result = Map.groupBy(inventory, ({ quantity }) => {
  return quantity > 5 ? stockStatus.ok : stockStatus.low;
});

// 你可以透過物件作為 Key 來取得資料
console.log(result.get(stockStatus.ok));
// 輸出 [{ name: "Item A", quantity: 10 }, { name: "Item C", quantity: 15 }]

為什麼要用 groupBy?

  1. 可讀性極佳: 代碼意圖非常明顯(我要分組)。
  2. 效能優化: 比自己寫的 reduce 邏輯更簡潔,且引擎內部可能會有針對性的優化。
  3. 符合直覺: 這是現代資料處理中最常見的需求之一,現在終於有了標準做法。

總結

Object.groupBy() 是處理 JSON 資料或一般物件陣列的首選;而如果你有更複雜的鍵值需求或需要 Map 的特性,則選用 Map.groupBy()。這兩個新工具極大地簡化了 JavaScript 的資料操作邏輯。