結論
flatMapを使用する。
// カテゴリー配列の中にitemsという配列オブジェクトがある。
const category = [
{id: 1,items: [{ id: 1, price: 500 },{ id: 2, price: 500 },],},
{id: 2,items: [{ id: 1, price: 1000 },{ id: 2, price: 300 },],},
]
// flatMapを使用して、itemsのみの配列を取得する
const items = category.flatMap((c) => c.items)
// 結果 (配列が1次元が下がる)
[ { id: 1, price: 500 },
{ id: 2, price: 500 },
{ id: 1, price: 1000 },
{ id: 2, price: 300 } ]
// reduceで合計値を算出する
const total = items.reduce((sum, item) => sum + item.price, 0)
console.log(total) // 2300
// 1度でやるならそのままつなげる。
const total = category
.flatMap((c) => c.items)
.reduce((sum, item) => sum + item.price, 0)
// 2300
概要
友達から、配列の中の配列の合計値を取得したいと言われて、「そんなん簡単やろ。手本見せたるわっ」と意気揚々と実演したが、詰まりかけたので解説。
mapを使うが動かん。
わい「配列の操作をしたいときはmapを使って、合計値はreduce使うと簡単に求められるで」
とも「ほえーー」
わい「まずは、itemsだけの配列つくってreduceすると分かりやすいんや」
const category = [
{id: 1,items: [{ id: 1, price: 500 },{ id: 2, price: 500 },],},
{id: 2,items: [{ id: 1, price: 1000 },{ id: 2, price: 300 },],},
]
const items = category.map((c) => c.items)
// エラーが起きる。
cosnt total = items.reduce((sum, item) => sum + item.price, 0)
わい「あれうごかん。。」
原因
mapは配列を返すメソッドなので、取り出した結果は、結局配列の中の配列になってしまう。
const items = category.map((c) => c.items)
// 結果
[ [ { id: 1, price: 500 }, { id: 2, price: 500 } ],
[ { id: 1, price: 1000 }, { id: 2, price: 300 } ] ]
無理やりやるとこうなる。
わい「あ、見づらくなるけど、reduce2回やればできるで」
とも「ほえー」
const items = category.map((c) => c.items)
const total = items.reduce((sum, current) => sum + current.reduce((sum, current) => sum + current.price, 0),0)
とも「見づらくてワイには分かりづらいな。」
わい「ちーん」
再結論
flatMapを使えば、配列の次元が低くなる。あとは、reduceで合計値を算出する。
const total = category
.flatMap((c) => c.items)
.reduce((sum, current) => sum + current.price, 0)
[参考]
https://qiita.com/NeGI1009/items/4befe4695a4712d96d56
感想
mapとreduceで簡単に出来ると思ったら、思わぬ落とし穴がありました。。
for ofとか使っても出来ると思いますが、配列メソッドでやりたいですよね。
jsにはまだまだ便利なメソッドがあると思うので、今後も少しずつ勉強して綺麗なコードにしたいと思います。
また、人に教えるときは、調子乗らないようにします。