Author: 水卜
Author: 水卜
サンプルコード
オブジェクト配列をあるプロパティでグルーピングしたい時のサンプル。
const groupBy = (array, property) => {
return array.reduce(
(group, item) => Object.assign(group, {
[item[property]]: (group[item[property]] || []).concat(item)
}),
{}
)
}
解説
reduceの仕様
Array.prototype.reduceは、配列の各値にアクセスし、最終的に1つの値を返す。
// 第一引数にコールバック関数、第二引数に初期値
arr.reduce(callback[, initialValue]);
// コールバック関数をそのまま書くと以下。
arr.reduce(
(accumulator, currentValue, currentIndex, array) => {
},
{}
);
callbackはaccumulator, currentValue, currentIndex, arrayの4つ引数をとる。
arr.reduceが呼ばれた時、コールバックのcurrentValueには配列の最初の要素が入る。
accumulator
accumulatorは初期値として空のオブジェクトが設定されている。
currentValue
currentValueは順番にアクセスしている配列の値が入る。
以下のforof文で言うとitemがここに入っている
for(const item of items) {};
currentIndex
currentIndexは前述のcurrentValueのインデックスである。
コールバック関数の中でarr[currentIndex - 1]
のように記述すれば配列の前の値にアクセスすることもできる。
array
reduceをかけた配列がそのまま入っている。
accumulatorは「蓄積するもの」といった意味を持つ。
その名の通り、reduce関数は配列の各値にアクセスしながらaccumulatorに値を蓄積し、最後に蓄積しきったaccumulatorを得るといった使い方をする。
サンプルコードのコールバック
以上を踏まえてサンプルコードのコールバックを見てみよう。
accumulatorとcurrentValueしか使っていない。今回はオブジェクト配列のグルーピングがお題なので、currentValueにはオブジェクトが入っている。
(group, item) => Object.assign(group, {
[item[property]]: (group[item[property]] || []).concat(item)
})
Object.assign(A, B)はAオブジェクトにBオブジェクトをコピー(同一のキーは上書き)し、Aオブジェクトを返すもの。
propertyをキーとしたオブジェクトを作成し、groupのpropertyにもしオブジェクトがあればitemをそこに追加し、なければ空の配列にitemを突っ込んだものを使っている。
これを配列の全要素で繰り返せば、propertyでグルーピングされたオブジェクトが手に入る。
lodashを使おう
なお、今までの話はlodashを使えば1秒で解決する。
npm install lodash
const _ = require('lodash');
_.groupBy([6.1, 4.2, 6.3], Math.floor);
// => { '4': [4.2], '6': [6.1, 6.3] }
// The `_.property` iteratee shorthand.
_.groupBy(['one', 'two', 'three'], 'length');
// => { '3': ['one', 'two'], '5': ['three'] }