簡體   English   中英

按多個鍵對數組對象求和

[英]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具有匹配latlng的先前條目,然后在最后獲取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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM