概要
配列の形で持っているデータをグループごとに集計したデータの形に変換したときの話。
こんなデータを
グループ | 目標 | 実績 |
---|---|---|
A | 100 | 200 |
A | 100 | 50 |
B | 50 | 100 |
こんな形に集計する
グループ | 目標 | 実績 |
---|---|---|
A | 200 | 250 |
B | 50 | 100 |
詳細
まずはreduceで呼び出す、集計処理の関数
hasOwnProperty
でマップに対象キーのデータが登録済みかどうかで判断している。
const convertDataMap = function(dataMap, d) {
const key = d.group1;
//const key = `${d.group1}-${d.group2}`; // keyの作り方次第で複合キーでの集計も可能
if (dataMap.hasOwnProperty(key)) {
const tmp = Object.assign({}, dataMap[key]);
dataMap[key] = {
target: tmp.target + d.target,
result: tmp.result + d.result
}
} else {
dataMap[key] = {
target: d.target,
result: d.result
}
}
return dataMap;
}
上記の関数を呼び出す部分
reduce
内でさっきの関数を呼びだす。
const data = [
{ "group1":"A","group2":"C", "target":100, "result":50 },
{ "group1":"A","group2":"D", "target":50, "result":50 },
{ "group1":"A","group2":"D", "target":10, "result":100 },
{ "group1":"B","group2":"D", "target":100, "result":50 },
{ "group1":"B","group2":"C", "target":50, "result":50 },
{ "group1":"B","group2":"C", "target":10, "result":100 },
]
const convertMap = data.reduce(convertDataMap, {});
作成後のデータの形はこんな感じ
変換後データ
{
"A": {
"target": 160,
"result": 200
},
"B": {
"target": 160,
"result": 200
}
}
データを配列の形にしたい場合は、以下のような処理をしてあげると
const _data = [...Object.entries(convertMap)].map(([key, value]) =>({key, value}));
配列になる(value の部分もフラットにしたい場合は、上記の関数のmap内の処理を書き換えてください)
変換後データ
[
{
"key": "A",
"value": {
"target": 160,
"result": 200
}
},
{
"key": "B",
"value": {
"target": 160,
"result": 200
}
}
]
まとめ
サーバー側で集計まで処理して返すことは結構あったが、JavaScriptでやるのは何気に初めてだった。
画面側で集計処理できれば、集計キーが複数あった場合の階層を変更してもリクエスト投げずに処理できてしまうので、今後も使いどころはあるかも。。。