JSON データの集計・グルーピング

API から取得した JSON データを集計したり、特定のキーでグループ化したりする方法を解説します。reduce() メソッドを中心に、実践的なデータ処理パターンを見ていきます。

合計値の計算

reduce() を使って、配列内の数値を合計します。

const orders = [
  { product: "りんご", price: 150, quantity: 3 },
  { product: "バナナ", price: 100, quantity: 5 },
  { product: "みかん", price: 80, quantity: 10 }
];

// 合計金額
const total = orders.reduce((sum, order) => {
  return sum + order.price * order.quantity;
}, 0);

console.log(total); // 1750

平均値の計算

合計を要素数で割って平均を求めます。

const scores = [
  { subject: "数学", score: 80 },
  { subject: "英語", score: 75 },
  { subject: "理科", score: 90 }
];

const average = scores.reduce((sum, item) => sum + item.score, 0) / scores.length;
console.log(average); // 81.666...

最大値・最小値の取得

reduce() または Math.max/min と組み合わせて求めます。

const products = [
  { name: "A", price: 1500 },
  { name: "B", price: 800 },
  { name: "C", price: 2200 }
];

// 最高価格の商品
const mostExpensive = products.reduce((max, p) => 
  p.price > max.price ? p : max
);

// 価格の最大値だけを取得
const maxPrice = Math.max(...products.map(p => p.price));

グループ化

特定のキーでデータをグループ化するのは、よく使うパターンです。

const users = [
  { name: "田中", department: "営業" },
  { name: "山田", department: "開発" },
  { name: "佐藤", department: "営業" },
  { name: "鈴木", department: "開発" },
  { name: "高橋", department: "人事" }
];

// 部署ごとにグループ化
const grouped = users.reduce((acc, user) => {
  const key = user.department;
  if (!acc[key]) {
    acc[key] = [];
  }
  acc[key].push(user);
  return acc;
}, {});

console.log(grouped);
// {
//   "営業": [{ name: "田中", ... }, { name: "佐藤", ... }],
//   "開発": [{ name: "山田", ... }, { name: "鈴木", ... }],
//   "人事": [{ name: "高橋", ... }]
// }

Object.groupBy()(ES2024)

ES2024 では Object.groupBy() が追加され、より簡潔に書けるようになりました。

const grouped = Object.groupBy(users, user => user.department);

カウント集計

各カテゴリの件数をカウントする場合です。

const votes = ["A", "B", "A", "C", "B", "A", "B", "A"];

const count = votes.reduce((acc, vote) => {
  acc[vote] = (acc[vote] || 0) + 1;
  return acc;
}, {});

console.log(count);
// { A: 4, B: 3, C: 1 }

複数キーでの集計

複数のキーを組み合わせて集計することもできます。

const sales = [
  { year: 2023, month: 1, amount: 100 },
  { year: 2023, month: 1, amount: 150 },
  { year: 2023, month: 2, amount: 200 },
  { year: 2024, month: 1, amount: 180 }
];

// 年月ごとの合計
const monthlyTotal = sales.reduce((acc, sale) => {
  const key = `${sale.year}-${sale.month}`;
  acc[key] = (acc[key] || 0) + sale.amount;
  return acc;
}, {});

console.log(monthlyTotal);
// { "2023-1": 250, "2023-2": 200, "2024-1": 180 }

汎用的なグループ化関数

再利用しやすいグループ化関数を作っておくと便利です。

function groupBy(array, keyFn) {
  return array.reduce((acc, item) => {
    const key = typeof keyFn === "function" ? keyFn(item) : item[keyFn];
    if (!acc[key]) {
      acc[key] = [];
    }
    acc[key].push(item);
    return acc;
  }, {});
}

// 使用例
groupBy(users, "department");
groupBy(users, user => user.name[0]); // 名前の頭文字でグループ化
reduce() のポイント

第2引数(初期値)を必ず指定する習慣をつけましょう。空配列の場合にエラーを防げます。

パフォーマンス

大量データの場合、reduce() は1回のループで完結するため効率的です。

集計とグループ化はデータ分析の基本です。これらのパターンを組み合わせることで、複雑なデータ処理も実現できます。