Alex
Alex

Reputation: 23

Loop through array of objects and return sum of certain values

I have an array of objects that contains results of a poll, which looks (for example) like this:

[
    {title: 'cat', optionid: 7, points: 1 }, 
    {title: 'cat', optionid: 7, points: 3 }, 
    {title: 'cat', optionid: 7, points: 1 }, 
    {title: 'dog', optionid: 8, points: 3 }, 
    {title: 'dog', optionid: 8, points: 2 }, 
    {title: 'dog', optionid: 8, points: 3 }, 
    {title: 'pig', optionid: 9, points: 2 }, 
    {title: 'pig', optionid: 9, points: 1 }, 
    {title: 'pig', optionid: 9, points: 1 }
]

Basically, I want to loop through and sum the points for each optionid/title. So cat = 5, dog = 8, and pig = 4. Is there any way to do this in JavaScript? All my attempts have failed so far. I'm self-taught and just a beginner, so the less complex the solution the better.

Upvotes: 2

Views: 3050

Answers (3)

Thomas Valadez
Thomas Valadez

Reputation: 1747

I think using reduce is the best way to go here. However it can be confusing for newbs like me. So here is a more straight forward approach. Hopefully this is a little easier to follow.

var animals = [{title: 'cat', optionid: 7, points: 1 },
{title: 'cat', optionid: 7, points: 3 },
{title: 'cat', optionid: 7, points: 1 },
{title: 'dog', optionid: 8, points: 3 },
{title: 'dog', optionid: 8, points: 2 },
{title: 'dog', optionid: 8, points: 3 },
{title: 'pig', optionid: 9, points: 2 },
{title: 'pig', optionid: 9, points: 1 },
{title: 'pig', optionid: 9, points: 1 }];

// create new object to store results in
newObj = {};

// loop through animal objects
animals.forEach(function(animal){
 // check if animal type has already been added to newObj
 if(!newObj[animal.title]){
  // If it is the first time seeing this animal type
  // we need to add title and points to prevent errors
  newObj[animal.title] = {};
  newObj[animal.title]['points'] = 0;
 }
 // add animal points to newObj for that animal type.
 newObj[animal.title]['points'] += animal.points 
})
console.log(newObj)

Upvotes: 2

xianshenglu
xianshenglu

Reputation: 5309

use reduce

let data = [
    { title: 'cat', optionid: 7, points: 1 },
    { title: 'cat', optionid: 7, points: 3 },
    { title: 'cat', optionid: 7, points: 1 },
    { title: 'dog', optionid: 8, points: 3 },
    { title: 'dog', optionid: 8, points: 2 },
    { title: 'dog', optionid: 8, points: 3 },
    { title: 'pig', optionid: 9, points: 2 },
    { title: 'pig', optionid: 9, points: 1 },
    { title: 'pig', optionid: 9, points: 1 }
];
let result = data.reduce((re, obj) => {
    let index = re.map(o => o.optionid).indexOf(obj.optionid);
    index > -1 ? re[index].points += obj.points : re.push(obj);
    return re;
}, []);
console.log(result);

Upvotes: 1

bugwheels94
bugwheels94

Reputation: 31910

It is pretty easy with reduce

var arr = [{title: 'cat', optionid: 7, points: 1 },
{title: 'cat', optionid: 7, points: 3 },
{title: 'cat', optionid: 7, points: 1 },
{title: 'dog', optionid: 8, points: 3 },
{title: 'dog', optionid: 8, points: 2 },
{title: 'dog', optionid: 8, points: 3 },
{title: 'pig', optionid: 9, points: 2 },
{title: 'pig', optionid: 9, points: 1 },
{title: 'pig', optionid: 9, points: 1 }]
var result = arr.reduce(function(acc, v) {
  acc[v.title] = (acc[v.title] || 0) + v.points
  return acc
}, {})
console.log(result)

Upvotes: 0

Related Questions