简体   繁体   中英

How to sum up values of same field in array of objects?

I have an array of objects

const data = [
  { category: 'shopping', amount: 50 }, 
  { category: 'rent', amount: 1000 }, 
  { category: 'groceries', amount: 20 }, 
  { category: 'shopping', amount: 50 }
]

and I am trying to sum up the amounts per category

const result = [
  { category: 'shopping', amount: 100 },
  { category: 'rent', amount: 1000 },
  { category: 'groceries', amount: 20 }
]

So far, I'm thinking of removing the 'duplicates' of categories and store them into an array

const temp = data.map((obj) => {
  return obj.category
})

const categories = [...new Set(temp)] // ['shopping','rent','groceries']

With the above, i'm thinking of doing a nested loop but after many tries, I have failed.

Any help is appreciated

You can use reduce() to do that.

Iterate on given data and if an item with same category as current item exists, then add the amount , else add current item as a new entry.

 const data = [ { category: 'shopping', amount: 50 }, { category: 'rent', amount: 1000 }, { category: 'groceries', amount: 20 }, { category: 'shopping', amount: 50 } ]; let result = data.reduce((acc, curr) => { let item = acc.find(item => item.category === curr.category); if (item) { item.amount += curr.amount; } else { acc.push(curr); } return acc; }, []); console.log(result);

Here is an alternative approach using object as the accumulator. This has a performance benefit as we wouldn't have to call find() on every iteration. Credits to frodo2975 for the suggestion.

 const data = [ { category: 'shopping', amount: 50 }, { category: 'rent', amount: 1000 }, { category: 'groceries', amount: 20 }, { category: 'shopping', amount: 50 } ]; let result = Object.values(data.reduce((acc, curr) => { let item = acc[curr.category]; if (item) { item.amount += curr.amount; } else { acc[curr.category] = curr; } return acc; }, {})); console.log(result);

I would focus on efficiently computing the totals for each category, and then restructuring the data in the format that you need. So something like this:

// Construct an object mapping category to total amount.
const totals = data.reduce((totals, { category, amount }) => {
    totals[category] = (totals[category] || 0) + amount;
}, {});

// Format the data as you like.
const result = Object.entries(totals).map(([category, amount]) => ({ category, amount });

Just another version of using reduce method:)

 const data = [ { category: 'shopping', amount: 50 }, { category: 'rent', amount: 1000 }, { category: 'groceries', amount: 20 }, { category: 'shopping', amount: 50 } ]; const result = data.reduce((a,c) => { a[c.category] = a[c.category] || {category: c.category, amount: 0}; a[c.category].amount += c.amount; return a; }, {}) console.log(Object.values(result));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM