Summing Records and Consolidating Based on IDs in Array

Viewed 31

I have an array of records that contain objects, each with an id and an amount. Now, in this array, some elements have the same id. What I need to do is iterate over this array, and first, sum up the values for records that have the same id, and then return just one record when that is the case - so I end up with an array with only unique ids -- each one also containing an amount property.

In other words, I want to take this array:

const records = [
  {id: 1, amount: 10},
  {id: 1, amount: 20},
  {id: 2, amount: 10},
  {id: 3, amount: 10},
  {id: 3, amount: -10}
];

... and produce this array:

const transformedRecords = [
  {id: 1, amount: 30},
  {id: 2, amount: 10},
  {id: 3, amount: 0}
];

I've thought about using a for-of loop for this, but that might bet pretty verbose, and I'm guessing there's a more succinct way to accomplish this - perhaps with reduce()? What's an elegant way to approach this, preferably using es6+ syntax?

2 Answers

You can use reduce() to create an object and then use map() on its entries to create array of objects back

const records = [
  {id: 1, amount: 10},
  {id: 1, amount: 20},
  {id: 2, amount: 10},
  {id: 3, amount: 10},
  {id: 3, amount: -10}
];
const res = Object.entries(records.reduce((ac, a) => {
  ac[a.id] = (a[a.id] || 0) + a.amount;
  return ac
}, {})).map(([id, amount]) => ({id, amount: amount < 0 ? 0 : amount}))

console.log(res)

Use Array.reduce, for each iteration, check if you have an object with the current id in the accumulator, if you do, add the amounts, if not, push the current object to the accumulator :

const records = [
  {id: 1, amount: 10},
  {id: 1, amount: 20},
  {id: 2, amount: 10},
  {id: 3, amount: 10},
  {id: 3, amount: -10},
  {id: 4, amount: -10},
  {id: 4, amount: -10}
];

const result = records.reduce((acc, curr) => {
  const ndx = acc.findIndex(e => e.id === curr.id);

  if(ndx > -1) {
    acc[ndx].amount += curr.amount
  }
  else{
    acc.push(curr)
  }

  return acc;
}, [])

console.log(result)

Related