[英]Sum array objects by multiple keys
我有一個包含 3 個鍵、lat、lng 和 value 的對象數組。 例如
let arr = [
{ lat: 20, lng: 30, value: 3 },
{ lat: 25, lng: 25, value: 4 },
{ lat: 20, lng: 30, value: 6 },
{ lat: 30, lng: 40, value: -5 },
{ lat: 25, lng: 25, value: 7 },
];
我想計算每個lat/lng對的總和,期望得到以下結果:
let res = [
{ lat: 20, lng: 30, value: 9 },
{ lat: 25, lng: 25, value: 11 },
{ lat: 30, lng: 40, value: -5 }
];
我試圖將結果存儲到一個中間對象中,如下所示:
const temp = res.reduce((acc, { lat, lng, value }) => {
acc[lat] = acc[lat] || {};
acc[lat][lng] = acc[lat][lng] || 0;
acc[lat][lng] += value;
return acc;
}, {});
所以 temp 看起來像這樣:
let temp = {
20: {
30: 9
},
25: {
25: 11
},
30: {
40: -5
}
};
然后將其轉換為我想要的格式:
let res = Object.keys(temp).reduce((acc, lat) => {
let tt = Object.keys(temp[lat]).map(lng => {
return {lat: lat, lng: lng, value: temp[lat][lng]};
});
acc.push(...tt);
return acc;
}, []);
這看起來效率很低,我相信有更聰明的方法來做到這一點。 我查看了 lodash 的 groupBy 和 sumBy,但我無法將解決方案放在一起。
您可以獲取一個平面對象並從中獲取值作為結果集。
一組鍵用於獲取連接的鍵。
let array = [{ lat: 20, lng: 30, value: 3 }, { lat: 25, lng: 25, value: 4 }, { lat: 20, lng: 30, value: 6 }, { lat: 30, lng: 40, value: -5 }, { lat: 25, lng: 25, value: 7 }], keys = ['lat', 'lng'], result = Object.values(array.reduce((r, o) => { const key = keys.map(k => o[k]).join('|'); if (!r[key]) r[key] = { ...o, value: 0 }; r[key].value += o.value; return r; }, {})); console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
我會遍歷並跟蹤Map
具有匹配lat
和lng
的先前條目,然后在最后獲取Map
的值:
const known = new Map();
for (const {lat, lng, value} of arr) {
const key = `${lat}:${lng}`;
const prev = known.get(key);
if (prev) {
prev.value += value;
} else {
known.set(key, {lat, lng, value});
}
}
const result = [...known.values()];
現場示例:
let arr = [ { lat: 20, lng: 30, value: 3 }, { lat: 25, lng: 25, value: 4 }, { lat: 20, lng: 30, value: 6 }, { lat: 30, lng: 40, value: -5 }, { lat: 25, lng: 25, value: 7 }, ]; const known = new Map(); for (const {lat, lng, value} of arr) { const key = `${lat}:${lng}`; const prev = known.get(key); if (prev) { prev.value += value; } else { known.set(key, {lat, lng, value}); } } const result = [...known.values()]; console.log(result);
你可以用reduce
做到這一點:
let arr = [ { lat: 20, lng: 30, value: 3 }, { lat: 25, lng: 25, value: 4 }, { lat: 20, lng: 30, value: 6 }, { lat: 30, lng: 40, value: -5 }, { lat: 25, lng: 25, value: 7 }, ]; const result = [...arr.reduce((map, {lat, lng, value}) => { const key = `${lat}:${lng}`; const prev = map.get(key); if (prev) { prev.value += value; } else { map.set(key, {lat, lng, value}); } return map; }, new Map()).values()]; console.log(result);
...但它不會給你帶來任何東西; 只是更容易出錯。 (我是許多相信除非您使用一組預定義的、可重用的 reducer 函數進行函數式編程的人之一,否則reduce
只是不必要的復雜化。)
我通常會做這樣的事情:
let arr = [ { lat: 20, lng: 30, value: 3 }, { lat: 25, lng: 25, value: 4 }, { lat: 20, lng: 30, value: 6 }, { lat: 30, lng: 40, value: -5 }, { lat: 25, lng: 25, value: 7 }, ]; const temp = arr.reduce((acc, { lat, lng, value }) => { const key = `${lat}:${lng}`; acc[key] = acc[key] || 0; acc[key] += value; return acc; }, {}); console.log(temp);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.