anabv
anabv

Reputation: 25

Javascript object sum values of same property key

I Have the following object and I want to sum the values of the same ingredients name, like: tomato: 5, chicken:5, rice: 1, peas: 1, i have this code but is not making the sum, instead is showing all the objects

var data3 = {
  "menus": [{
    "recipe": "chicken with rice",
    "ingredients": [{
      "name": "tomato",
      "value": 2
    }, {
      "name": "chicken",
      "value": 3
    }, {
      "name": "rice",
      "value": 1
    }]
  }, {
    "recipe": "Garden rice",
    "ingredients": [{
      "name": "tomato",
      "value": 3
    }, {
      "name": "chicken",
      "value": 2
    }, {
      "name": "peas",
      "value": 1
    }]
  }]
};

var ingredients;

for (var i = 0; i < 10; i++) {
  ingredients = data3.menus[i].ingredients;

  var temp = {};
  var obj = null;
  for (var j = 0; j < ingredients.length; j++) {
    obj = ingredients[j];

    if (!temp[obj.name]) {
      temp[obj.name] = obj;
    } else {
      temp[obj.name].value += obj.value;
    }

  }
  var result = [];
  for (var prop in temp)
     result.push(temp[prop]);

  console.log(result);

};

I will appreciate your help, thanks!

Upvotes: 2

Views: 1839

Answers (3)

dominik791
dominik791

Reputation: 752

You can create a function that will traverse all ingredients and if ingredient.name has given name, then add ingredient.value to your result. Here is ES2015 solution with arrow functions:

const sumIngredients = (menus, name) => {
  let result = 0;
  menus.forEach(meal => {
    meal.ingredients.forEach(ingredient => {
      if (ingredient.name === name) {
        result += ingredient.value;
      }
    })
  })
  return result;
}

The use it:

sumIngredients(data3.menus, 'chicken'); //5
sumIngredients(data3.menus, 'tomato'); //5 
sumIngredients(data3.menus, 'rice'); //1
sumIngredients(data3.menus, 'peas'); //1

Working example: https://jsfiddle.net/sc8wrupk/

Upvotes: 0

user1211
user1211

Reputation: 1515

Your implementation is correct, just you were re-initializing temp again and again. So you just need to take temp out of your for loop.

var data3 = {
  "menus": [{
    "recipe": "chicken with rice",
    "ingredients": [{
      "name": "tomato",
      "value": 2
    }, {
      "name": "chicken",
      "value": 3
    }, {
      "name": "rice",
      "value": 1
    }]
  }, {
    "recipe": "Garden rice",
    "ingredients": [{
      "name": "tomato",
      "value": 3
    }, {
      "name": "chicken",
      "value": 2
    }, {
      "name": "peas",
      "value": 1
    }]
  }]
};

var ingredients;
var temp = {};
for (var i = 0; i < data3.menus.length; i++) {
  ingredients = data3.menus[i].ingredients;

  var obj = null;
  for (var j = 0; j < ingredients.length; j++) {
    obj = ingredients[j];


    if (!temp[obj.name]) {
      temp[obj.name] = obj;
    } else {
      temp[obj.name].value += obj.value;
    }
  }
};

var result = [];
  for (var prop in temp)
     result.push(temp[prop]);
  console.log(result);

Upvotes: 0

Nina Scholz
Nina Scholz

Reputation: 386578

You could use a hash table with the name of the ingredient and use a default value of zero if a property does not exist. Then add the value.

var data3 = { menus: [{ recipe: "chicken with rice", ingredients: [{ name: "tomato", value: 2 }, { name: "chicken", value: 3 }, { name: "rice", value: 1 }] }, { recipe: "Garden rice", ingredients: [{ name: "tomato", value: 3 }, { name: "chicken", value: 2 }, { name: "peas", value: 1 }] }] },
    ingredients = Object.create(null);

data3.menus.forEach(function (a) {
    a.ingredients.forEach(function (b) {
        ingredients[b.name] = (ingredients[b.name] || 0) + b.value;
    });
});

console.log(ingredients);

Upvotes: 4

Related Questions