LoginSignup
0

More than 3 years have passed since last update.

プロパティによってオブジェクトをグループ化したい

Posted at

プロパティによってオブジェクトをグループ化したいです

オブジェクトの配列を、プロパティによってグループ化したいです。
想定するデータは以下のような感じです。

const data = [
  { type: '野菜', color: '', name: 'トマト' },
  { type: '野菜', color: '', name: 'パプリカ' },
  { type: '野菜', color: '', name: 'ブロッコリー' },
  { type: '果物', color: '', name: 'ぶどう' },
];

最終的に望む形式は以下のような感じです。

const groupingData = {
  '野菜': {
    '': ['トマト', 'パプリカ'],
    '': ['ブロッコリー'],
  },
  '果物': {
    '': ['ぶどう'],
  },
};

MDNにやりたいことが載ってた

まさにずばりやりたいことがそのまま載ってました。
Array.prototype.reduce()を使います。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce#Grouping_objects_by_a_property

// MDNに載っていたコードそのまま抜粋
return objectArray.reduce(function (acc, obj) {
  let key = obj[property]
  if (!acc[key]) {
    acc[key] = []
  }
  acc[key].push(obj)
  return acc
}, {});

今回の形式バージョンを考えました

// MDNに載っていたコードを少し改造
const groupBy = (objectArray, property, optionProperty = '') => {
  return objectArray.reduce((acc, obj) => {
    const key = obj[property];
    if (!acc[key]) {
      acc[key] = [];
    }
    if (optionProperty && obj.hasOwnProperty(optionProperty)) {
        acc[key].push(obj[optionProperty]);
    } else {
        acc[key].push(obj);
    }
    return acc;
  }, {});
};

// 階層構造にする
const createGroupingData = (objectArray, property1, property2, property3) => {
    const groupingData = groupBy(objectArray, property1);
    Object.keys(groupingData).forEach((key) => {
        groupingData[key] = groupBy(groupingData[key], property2, property3);
    });
    return groupingData;
};

// 使い方
const groupingData = createGroupingData(data, 'type', 'color', 'name');

もっと良い方法を教えて下さい。
再帰的な感じにしたいです。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0