JavaScriptでオブジェクト配列内の同じ名前の値を合計して集約する方法
JavaScriptでは、同じキーを持つ複数のオブジェクトが混在する配列を扱う場面がよくあります。例えば、以下のようなオブジェクトの配列を考えてみましょう。
const arr = [
{"firstName":"John", "value": 89},
{"firstName":"Peter", "value": 151},
{"firstName":"Anna", "value": 200},
{"firstName":"Peter", "value": 22},
{"firstName":"Anna","value": 60}
];ここで求められているのは、このような配列を引数として受け取り、firstNameプロパティの値が同じオブジェクト同士をグループ化し、valueプロパティを合計して1つのオブジェクトにまとめるJavaScript関数を作成することです。
したがって、上記の配列の場合、期待される出力は次のようになります。
const output = [
{"firstName":"John", "value": 89},
{"firstName":"Peter", "value": 173},
{"firstName":"Anna", "value": 260}
];この問題の文脈における「類似のオブジェクト」とは、firstNameの値が同じであるオブジェクトを指します。各オブジェクトに対して順に同じfirstNameを持つオブジェクトを探し、見つかった場合はvalueプロパティの値を先頭のオブジェクトに加算し、重複するオブジェクトは結果に含めないようにします。この処理を配列の末尾まで繰り返すことで、重複のない合計済みの配列が得られます。
実装例
以下がそのコードです。
const arr = [
{"firstName":"John", "value": 89},
{"firstName":"Peter", "value": 151},
{"firstName":"Anna", "value": 200},
{"firstName":"Peter", "value": 22},
{"firstName":"Anna","value": 60}
];
const sumSimilar = arr => {
const res = [];
for(let i = 0; i < arr.length; i++){
const ind = res.findIndex(el => el.firstName === arr[i].firstName);
if(ind === -1){
res.push(arr[i]);
}else{
res[ind].value += arr[i].value;
};
};
return res;
};
console.log(sumSimilar(arr));このコードでは、結果を格納する配列resを用意し、元の配列を1つずつ走査します。findIndex()で同じfirstNameを持つ要素が既に存在するかを確認し、存在しない場合は新しく追加、存在する場合は該当要素のvalueに加算します。
出力結果
コンソールには次のように出力されます。
[
{ firstName: 'John', value: 89 },
{ firstName: 'Peter', value: 173 },
{ firstName: 'Anna', value: 260 }
]別のアプローチ:reduce()を使った効率的な方法
より関数型プログラミングらしい書き方として、Array.prototype.reduce()を活用する方法もあります。
const sumSimilar = arr => {
const map = arr.reduce((acc, obj) => {
if (acc[obj.firstName]) {
acc[obj.firstName].value += obj.value;
} else {
acc[obj.firstName] = { ...obj };
}
return acc;
}, {});
return Object.values(map);
};
console.log(sumSimilar(arr));この方法では、一時的なオブジェクトをマップとして使い、firstNameをキーにして値を蓄積していきます。最後にObject.values()で配列に変換すれば、同じ結果が得られます。ネストしたループが不要なため、計算量はO(n)となり、大規模な配列でも効率的に処理できるのが利点です。
-
【JavaScript】配列内のネストされたオブジェクトの値を合計する方法
この記事では、JavaScriptを使って、配列内にネストされた(入れ子構造の)オブジェクトの値を合計する方法を解説します。サンプルコードでは、JSONデータの複数階層に格納された数値(costNum)を順番に取り出し、その合計をブラウザ上に表示します。 コード例 <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=d
-
JavaScriptで2つのオブジェクトを比較しながら配列のネストされた値をグループ化する方法
この記事では、2つのオブジェクト(before と after)を比較しながら、ネストされた配列の値を1つの行にグループ化する方法を解説します。データの差分を表形式で整理したい場合などに役立つテクニックです。入力データの例まず、次のようなJSONオブジェクトがあるとします。before(変更前)と after(変更後)の2つの状態が含まれ、それぞれの device 配列の中に、id、price、features(機能名と価格)というネストされた構造を持っています。const input = { before: { device: [ { id: 1234