注意
あらかじめ言っておきますが、筆者は初心者なので、自分なりの解釈でまとめています。「100%信じるぜ!」という気持ちで読まないようお願いします。どうぞよろしく!
参考資料
経緯
ポートフォリオを作成している際、以下のような課題に直面しました。
たとえば、以下のような ingredients
テーブルがあったとします。
このテーブルを使って「レシピごとの材料を集計」したい場面です。
たとえば「レシピ番号 2 と 3 を選んだら、たまねぎが 2 個になる」といった処理をしたいと考えました。
ingredients テーブルの例
レシピ番号 | 材料 | 数 | 単位 |
---|---|---|---|
1 | じゃがいも | 1 | 本 |
1 | 人参 | 1 | 本 |
1 | 豚肉 | 300 | g |
2 | たまねぎ | 1 | 個 |
2 | 豚肉 | 500 | g |
3 | たまねぎ | 1 | 個 |
3 | ひき肉 | 500 | g |
3 | 卵 | 2 | 個 |
3 | 片栗粉 | 少々 |
このように、材料名と単位が整っていれば、単純に for
文などで集計処理できそうです。
ただし、以下のように同じ材料で単位が異なる場合(例:たまねぎが "300g" と "1個")、どのように集計するか悩みました。
単位がバラバラなパターン(例)
レシピ番号 | 材料 | 数 | 単位 |
---|---|---|---|
1 | じゃがいも | 1 | 個 |
1 | 人参 | 1 | 本 |
1 | 豚肉 | 300 | 個 |
2 | たまねぎ | 300 | g |
2 | 豚肉 | 500 | g |
3 | たまねぎ | 1 | 個 |
3 | ひき肉 | 500 | g |
3 | 卵 | 2 | 個 |
3 | 片栗粉 | 少々 |
そこで、ChatGPT に聞いたところ「Map 関数を使うといいよ!」というヒントをもらい、調べてまとめてみることにしました。
Mapとは?
Map とは
Map
は、キーと値を柔軟に設定できるコレクションです。
通常のオブジェクト({}
)ではキーが文字列か記号に限定されますが、Map は任意の値をキーに使えます。
キーの違い
オブジェクトの場合:
const obj = {
name: "taro",
age: 28
};
Mapの場合
const map = new Map();
map.set(1, "taro");
map.set("age", 28);
上記のように、1 のような数値をキーにできるのが特徴です。
Mapの操作
// 新しく Map を作成
const map = new Map();
// 値を追加
map.set(key, value);
// キーの存在確認
map.has(key);
// 値を取得
map.get(key);
などのメソッドが用意されています。
等々で紹介しましたが、詳細は MDN を参照ください
その他
Map はオブジェクトと同様に forEach
を使った反復処理が可能です。
MDNより引用
myMap.forEach((value, key) => { console.log(`${key} = ${value}`); }); // 0 = zero // 1 = one
「Map便利。じゃあオブジェクトいらない?」。
一見すると Map は非常に便利に見えますが、オブジェクトにも使いやすさがあります。
たとえば、Map で初期データをセットするには:
map1.set("a", 1);
map1.set("b", 2);
map1.set("c", 3);
一方、オブジェクトなら簡潔に書けます:
const test = {
'a':1,
'b':2,
'c':3,
}
そのため、初期設定が多い場合や JSON として扱いたい場合はオブジェクトの方が適しています。
今回の使用方法
まずは、Mapの作成
const sumIngredints = new Map<string, IngredientsType>
ingredients
配列を forEach
で回して集計する
ingredients.forEach(i => {
//以下のようにMapに設定するキーを設定する。今回は、材料の名前と単位をキーとした。
const key = `${i.ingredientName}_${i.IngredientUnit}`
//Mapにキーが有るかどうかを判定して、なければ、Mapにセットする。
if (!sumIngredints.has(key)) {
sumIngredints.set(key, {
ingredientName: i.ingredientName,
ingredientQuantity: i.ingredientQuantity,
ingredientUnit: i.IngredientUnit
})
//キーがあれば、それに数量を足すことになる
} else {
sumIngredints.get(key)!.ingredientQuantity += i.ingredientQuantity
}
このようにして、材料名+単位をキーとして、材料の合計数量を算出できます。
感想
Map関数は非常に協力だと感じました。ただ、、使いやすいパターンと使いにくいパターンがあると思うので、今後も使い分けを意識していきたいです。ガンガンアプリ開発していこう。