Object.groupByで配列グルーピングを一行で完結する

問題

配列を特定の基準でグルーピングするたびにreduceを書く必要がありました。毎回初期値を設定し、キーの存在チェックをして、配列にpushして… 単純なグルーピングなのにコードが5行以上になるのは少し煩わしいものです。

// 毎回これを書いていました
const grouped = items.reduce((acc, item) => {
  const key = item.category;
  if (!acc[key]) acc[key] = [];
  acc[key].push(item);
  return acc;
}, {});

解決方法

ES2024で追加されたObject.groupByを使えば一行で済みます。

const items = [
  { name: 'りんご', category: '果物' },
  { name: 'にんじん', category: '野菜' },
  { name: 'バナナ', category: '果物' },
  { name: 'ほうれん草', category: '野菜' },
];

const grouped = Object.groupBy(items, (item) => item.category);
// {
//   '果物': [{ name: 'りんご', ... }, { name: 'バナナ', ... }],
//   '野菜': [{ name: 'にんじん', ... }, { name: 'ほうれん草', ... }]
// }

実務でよく使うパターンです:

// ステータス別に注文を分類
const orders = [
  { id: 1, status: 'pending' },
  { id: 2, status: 'shipped' },
  { id: 3, status: 'pending' },
];
const byStatus = Object.groupBy(orders, (o) => o.status);

// 日付別にログをグルーピング
const logs = [
  { msg: 'error', date: '2026-03-14' },
  { msg: 'info', date: '2026-03-14' },
  { msg: 'warn', date: '2026-03-13' },
];
const byDate = Object.groupBy(logs, (log) => log.date);

// 条件付きグルーピング(成人/未成年)
const users = [
  { name: 'Kim', age: 25 },
  { name: 'Lee', age: 17 },
];
const byAge = Object.groupBy(users, (u) => u.age >= 18 ? 'adult' : 'minor');

ポイント

  • Object.groupByはnullプロトタイプオブジェクトを返します。hasOwnPropertyチェックは不要です
  • キーにシンボルを使いたい場合はMap.groupByを使います
  • Node.js 21+、Chrome 117+、Safari 17.4+でサポートされています。古いブラウザにはcore-jsポリフィルで対応できます