zukucode
主にWEB関連の情報を技術メモとして発信しています。

JavaScript オブジェクト配列をsqlのgroup byのように集計する

JavaScriptのオブジェクト配列(jsonも同様)をSQLGROUP BYのように集計します。

具体的には以下のようなことができるようになります。

var arr = [
  {
    name: 'バナナ',
    category: 'フルーツ',
    price: 100
  },
  {
    name: 'りんご',
    category: 'フルーツ',
    price: 120
  },
  {
    name: 'みかん',
    category: 'フルーツ',
    price: 30
  },
  {
    name: 'トマト',
    category: '野菜',
    price: 200
  },
  {
    name: 'キャベツ',
    category: '野菜',
    price: 150
  }
];

// 集計後
// カテゴリーごとの個数(要素数)と金額を集計
[
  {
    category: 'フルーツ',
    count: 3,
    price: 150
  },
  {
    category: '野菜',
    count: 2,
    price: 350
  },
];

実装方法

いろいろとやり方はあるかと思いますが、今回はreduce関数を使用します。

reduce関数の使い方についてはJavaScript reduce関数の基本的な使い方で紹介しています。

var group = arr.reduce(function (result, current) {
  var element = result.find(function (p) {
    return p.category === current.category
  });
  if (element) {
    element.count ++; // count
    element.price += current.price; // sum
  } else {
    result.push({
      category: current.category,
      count: 1,
      price: current.price
    });
  }
  return result;
}, []);

console.log(group);
/* 出力結果
[
  {
    category: 'フルーツ',
    count: 3,
    total: 150
  },
  {
    category: '野菜',
    count: 2,
    price: 350
  },
]
*/

reduce関数は慣れていないとわかりづらいかもしれませんが、使いこなせればとても簡単に配列やオブジェクトを集計できるようになります。

ES2015の表記

アローファンクションやconstを使用するとさらにシンプルになります。

const group = arr.reduce((result, current) => {
  const element = result.find((p) => p.category === current.category);
  if (element) {
    element.count ++; // count
    element.price += current.price; // sum
  } else {
    result.push({
      category: current.category,
      count: 1,
      price: current.price
    });
  }
  return result;
}, []);

IE8以下の対応

IE8以下はreduce関数が使用できません。

下記のURLで紹介されているfunctionを実装すればreduce関数を使用できるようになります。

Array.prototype.reduce() - JavaScript | MDN


関連記事