bier hier
bier hier

Reputation: 22520

How to calculate the sum of items in an array?

Suppose i have an array:

const items = [
  {
    "amount1": "100",
    "amount2": "50",
    "name": "ruud"
  },
  {
    "amount1": "40",
    "amount2": "60",
    "name": "ted"
  }
]

I want to get all amount1 and amount2 props totalled and result in:

[
  {
    "amount1": 140,
    "amount2": 110
  }
]

How can I do this?

Upvotes: 0

Views: 116

Answers (6)

Kaiido
Kaiido

Reputation: 136598

reduce() is indeed the way to go, but the cleanest to go only through a set of known keys is probably to pass your expected result as the accumulator and to iterate over this accumulator's keys:

const items = [
  { amount1: "100", amount2: "50", name: "ruud", foo: "unrelated" },
  { amount1: "40", amount2: "60", name: "ted", foo: "0" }
];

const result = items.reduce((acc, item) => {
  for (let key in acc) { // iterate over the accumulator's keys
    acc[key] += isNaN(item[key]) ? 0 : +item[key];
  }
  return acc;
}, { // here we define the expected format
  amount1: 0,
  amount2: 0
});

console.log(result);

Upvotes: 0

Robby Cornelissen
Robby Cornelissen

Reputation: 97120

Using Array.prototype.reduce() with Object.entries() and Array.prototype.forEach():

const items = [{amount1: 100, amount2: 50}, {amount1: 40, amount2: 60}];

const sums = items.reduce((acc, item) => {
  Object.entries(item).forEach(([k, v]) => acc[k] = (acc[k] || 0) + v);
  return acc;
}, {});

console.log(sums);

To filter out non-number properties (but keep quoted number strings, as per the updated question):

const items = [{amount1: '100', amount2: '50', name: 'Ruud'}, {amount1: '40', amount2: '60', name: 'Ted'}];

const sums = items.reduce((acc, item) => {
  Object.entries(item)
        .filter(([_, v]) => !isNaN(v))
        .forEach(([k, v]) => acc[k] = (acc[k] || 0) + Number(v));
  return acc;
}, {});

console.log(sums);

Upvotes: 2

Maheer Ali
Maheer Ali

Reputation: 36564

You can use reduce().

  • Use the reduce() method on the array items
  • Set the accumulator(ac) as an empty object i.e {}
  • During each iteration through the objects create a for..in loop to iterate through all keys of object.
  • Check if the typeof value of key is "number" then add it otherwise don't

const items = [{amount1:100, amount2:50, name:"ruud"}, {amount1:40,amount2:60,name:"ted"}]

let res = [items.reduce((ac,x) => {
  for(let key in x){
    if(typeof x[key] === "number"){
      if(!ac[key]) ac[key] = 0;
      ac[key] += x[key]
    }
  }
  return ac;

},{})]
console.log(res)

Upvotes: 0

Murali Nepalli
Murali Nepalli

Reputation: 1618

Above solutions are great. I included this if you don't want to use Array.prototype.reduce(). This will work even if you have other properties which are not "numbers"

 const items = [{amount1: 100, amount2: 50, name: 'Ruud'}, {amount1: 40, amount2: 60, name: 'Ted'}];
 var result = {};

 items.forEach(function(eachItem){
    for(var prop in eachItem){
        if(typeof eachItem[prop] === "number"){
           result[prop] = result[prop] ? result[prop] + eachItem[prop] : eachItem[prop];                 
        }                
     }
 });
 result = [result];
 console.log(result);

Upvotes: 0

holydragon
holydragon

Reputation: 6728

Here is an alternative, simple, and clean solution for this.

const items = [{amount1:100, amount2:50, name:"ruud"},{amount1:40,amount2:60,name:"ted"}]
let result = [{amount1:0,amount2:0}]
items.forEach(i=>{
  result[0].amount1 += i.amount1
  result[0].amount2 += i.amount2
})
console.log(result)

Upvotes: 0

David Zambrano
David Zambrano

Reputation: 658

const items = [{amount1: 100, amount2: 50}, {amount1: 40, amount2: 60}];
function sum(data){
 const keys =  Object.keys(data[0])
 let res = {}
 for(key of keys)
   res[key]=data.map(x=>x[key]).reduce((a,b)=>a+b);
return res
  
}

console.log(sum(items))

Upvotes: 0

Related Questions