1

What would be the best way to sort myarr into sortedArr so that all of the values have been added together for each invidual id using javascript?

myarr = [{id: 10, val:100}, {id:10, val: 100}, {id:20, val:200}, {id:20, val:100}, {id:30, val:100}]

sortedArr = [{id: 10, val: 200}, {id:20, val:300}, {id:30, 100}]
Shipyard
  • 11
  • 1
  • 1
    Welcome to Stack Overflow! Please take the [tour] and read through the [help], in particular [*How do I ask a good question?*](/help/how-to-ask) Do your research, [search](/help/searching) for related topics on SO, and give it a go. ***If*** you get stuck and can't get unstuck after doing more research and searching, post a [mcve] of your attempt and say specifically where you're stuck. People will be glad to help. Good luck! – T.J. Crowder May 14 '18 at 14:58
  • 8
    That's not called *sorting*, that's called grouping (by the id property, in your case). – Bergi May 14 '18 at 14:59
  • 1
    Thanks bergi, your comment lead me to this thread https://stackoverflow.com/questions/14446511/what-is-the-most-efficient-method-to-groupby-on-a-javascript-array-of-objects – Shipyard May 14 '18 at 15:05

4 Answers4

1

First sum the values per ID, then push them to a new array.

let myarr = [{ id: 10, val: 100 }, { id: 10, val: 100 }, { id: 20, val: 200 }, { id: 20, val: 100 }, { id: 30, val: 100 }]
let group = {}

myarr.forEach((value, index) => {
    if (group[value.id]) {
        group[value.id] += value.val
    }
    else {
        group[value.id] = value.val
    }
})

let res = []

Object.keys(group).forEach((key) => {
    res.push({ id: key, val: group[key] })
})

console.log(res);
ninesalt
  • 4,054
  • 5
  • 35
  • 75
0

You need to keep a map of keys (hits) and reduce the original array. You can sort it afterwards, because the array will be smaller which speeds up sorting.

var myArr = [{id: 10, val:100}, {id:10, val: 100}, {id:20, val:200}, {id:20, val:100}, {id:30, val:100}];
var sortedArr = accumulateAndSortById(myArr, 'id', 'val');

console.log(sortedArr);

function accumulateAndSortById(arr, field, value) {
  var hitMap = arr.reduce((result, item) => {
    result[item[field]] = (result[item[field]] || 0) + item[value];
    return result;
  }, {});
  return Object.keys(hitMap).reduce((result, key) => {
    var obj = {};
    obj[key] = hitMap[key];
    result.push(obj);
    return result;
  }, []).sort((a, b) => a[field] > b[field]);
}
.as-console-wrapper { top: 0; max-height: 100% !important; }
Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132
0

You can do:

const myArr = [{id: 10, val:100}, {id:10, val: 100}, {id:20, val:200}, {id:20, val:100}, {id:30, val:100}]
const temp = myArr.reduce((a, c) => (a[c.id] = (a[c.id] || 0) + c.val, a), {});
const sortedArr = Object.keys(temp).map(k => ({id: +k, val: temp[k]}));

console.log(sortedArr);
Yosvel Quintero
  • 18,669
  • 5
  • 37
  • 46
-2

Use the following compare function to sort:

      var myArr =  [{id: 10, val:100}, {id:10, val: 100}, {id:20, val:200}, {id:20, val:100}, {id:30, val:100}];

  function compare(a,b) {
  if (a.id < b.id)
    return -1;
  if (a.id > b.id)
    return 1;
  return 0;
}

var sortedArr  = myArr.sort(compare);
iStepashka
  • 302
  • 1
  • 6