背景
受け取った値をreduceメソッドでカテゴリー毎に分け、分けたものに対し各種処理を行う必要のある場面がありましたので、「reduceメソッドでカテゴリー毎に分ける」部分をメモしておきたい背景となります。
該当のデータ
type Item = {
category: string;
name: string;
price: number;
};
const items: Item[] = [
{ category: "A", name: "A1", price: 100 },
{ category: "A", name: "A2", price: 200 },
{ category: "B", name: "B1", price: 300 },
{ category: "B", name: "B2", price: 400 },
{ category: "C", name: "C1", price: 500 },
];
このようにcategoryプロパティでカテゴリー分けがされているのですが、「カテゴリーA(もしくはB・C)の全てのアイテムに対し処理を加えたい」という場合があるので、reduceメソッドで分けていきます。
reduceメソッド
まずは基本構文です。
// テストデータ
const testArray = [1, 2, 3, 4, 5];
// reduceメソッドを使用して配列の合計値を求めます。
// 引数には(蓄積する変数(accumulator)、繰り返しを行なっている配列の現在の値(currentValue))が入ります。
// 第二引数には初期値が入ります。この場合、0を初期値として渡しています。
const sumValue = testArray.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
// 15で出力されます(1 + 2 + 3 + 4 + 5 = 15)
console.log(sumValue);
カテゴリー毎に分ける
続いて、先ほどのデータをカテゴリ毎に分別していきましょう。
全体のコード
type Item = {
category: string;
name: string;
price: number;
};
const items: Item[] = [
{ category: "A", name: "A1", price: 100 },
{ category: "A", name: "A2", price: 200 },
{ category: "B", name: "B1", price: 300 },
{ category: "B", name: "B2", price: 400 },
{ category: "C", name: "C1", price: 500 },
];
// ①
const grouped = items.reduce((acc: { [key: string]: Item[] }, item: Item) => {
// ②
if (!acc[item.category]) {
acc[item.category] = [];
}
// ③
acc[item.category].push(item);
// ④
return acc;
}, {});
console.log(grouped);
// {
// A: [
// { category: 'A', name: 'A1', price: 100 },
// { category: 'A', name: 'A2', price: 200 }
// ],
// B: [
// { category: 'B', name: 'B1', price: 300 },
// { category: 'B', name: 'B2', price: 400 }
// ],
// C: [ { category: 'C', name: 'C1', price: 500 } ]
// }
①蓄積値をオブジェクト型とし、キーと値に片付けを行う
// ①
const grouped = items.reduce((acc: { [key: string]: Item[] }, item: Item) => {},{});
蓄積値であるaccumulator(acc)をオブジェクト型{}で型付けを行い、内部のプロパティ名を[key: string]、値をItem[]という形にし、各種カテゴリ名がプロパティ名となり、値にそのカテゴリのアイテムがItem型で格納される形とします。
②繰り返し処理が新しいカテゴリーの番になったら空の値を作成
// ②
if (!acc[item.category]) {
acc[item.category] = [];
}
各種繰り返し処理時、蓄積値に該当のカテゴリーがあるかを検索し、存在しない場合にそのカテゴリをプロパティ名、値を空の配列としたものを作成する
③蓄積値に存在する該当カテゴリーにアクセスし、配列に値をpushする
// ③
acc[item.category].push(item);
蓄積値にブラケット記法でアクセスを行い、その値が配列なのでitemをpushメソッドで値に追加する。
※pushメソッドは配列の後尾に引数の値を追加するメソッドです。
④蓄積した値を返す
// ④
return acc;
returnで蓄積値を返してあげることで、次の繰り返し時にaccが蓄積された状態になる。
まとめ
オブジェクト型データの値がカテゴリ毎に存在している場合、reduceメソッドで各種カテゴリの配列を作成することが可能。
今回は自作APIを叩いて受け取った値が上記の形でしたが、API側でカテゴリ毎に出力するエンドポイントを作ってあげれば解決するので、今後はそのように変更していきたいです。