やりたいこと
下のような連想配列(オブジェクト)の配列があったときに、同じkeyの値の合計を求めたいことがありました。(きれいなデータを想定しています。valueはすべて数値です。)
const objs = [
{key1: 100, key2: 200, key3: 300},
{key1: 100, key2: 150, key3: 100},
{key1: 100, key3: 200, key4: 100},
]
sumObjects(objs)
// {key1: 300, key2: 350, key3: 600, key4: 100}
シンプルに書けないかと考えてはみたのですが、うまい書き方が見つかりません(Python3.9のように単純に足す(+)ことはできない)。
なので、結局
「結果を入れる空の連想配列を用意して、配列の中の連想配列を1コずつ見ていく。その中のkeyごとに値を足していく。」
という手続きをそのまま書きました。
やったこと
function sumObjects(objs) {
return objs.reduce((res, obj) => {
for (key in obj) {
key in res? res[key] += obj[key]: res[key] = obj[key]
}
return res
}, {})
}
とりあえず書いてしまいましたが、もっとうまい書き方を募集中です。
※ @standard-software さんに指摘いただいた内容を修正しました。(2020-10-17 06:11追記)
修正前のコードはreduce
に初期値が指定されておらず、引数のオブジェクトを破壊していました。
気を付けたこと
・4行目、res[key] += obj[key]
だけで大丈夫かなと思ったのですが、連想配列に存在しないキーを指定するとundefined
となり、足した結果がNaN
となってしまいダメでした。
終わりに
たぶん、Pythonのcollections.Counter
のように、この問題に適した道具があるんだろうなと思いつつ書きました。
良い方法を見つけたら書き足したいと思います。
※ いただいたコメントがとても良い内容ばかりです。(2020-10-17 06:11追記)
本文よりもむしろコメント欄のほうを見てもらいたい気持ちでいっぱいです。ぜひどうぞ!
以上、お読みいただきありがとうございました。