How to merge object of array and only increase amount property? Javascript array of objects

I am creating a recipe book application in Angular 7 which has a shopping list feature.

What I want:

When a person adds recipe ingredients to shopping list twice it increases only the amount of the ingredient obj.amount.

What Happens:

When a person clicks add an ingredient to the shopping list twice it creates another object of the same properties and shows the ingredient twice in the list.

What I want:

When someone clicks add ingredient twice it increases the object.amount where object.name are the same rather than creating a new object and showing a new list.

import { Ingredients } from './ingredient.model';
import { EventEmitter } from '@angular/core';

export class ShoppingListService {
  ingredientsChanged = new EventEmitter<Ingredients[]>();
  ingredient: Ingredients[] = [
    new Ingredients('Apple', 10),
    new Ingredients('Banana', 10)
  ];

  getData() {
    return this.ingredient.slice();
  }
  addIngredient(ingredient: Ingredients) {
    this.ingredient.push(ingredient);
    this.ingredientsChanged.emit(this.ingredient.slice());
  }
  toShoppingList(ingredient: Ingredients[])
  //I want to detect duplicate ingredient obj and increase 
  //ingredient.amount 
  //having same ingredient name 
  //i.e. suppose I add Apple again with amount 5
  //it should change the amount of {new Ingredient('Apple',15)} but should 
  //not 
  //create new object.
  {
    // METHOD 1 Loop through the array and add each element one by one
    for (let ing of ingredient) {
      this.addIngredient(ing);
    }
    // METHOD 2 : Add all ingredients at once
    // this.ingredient.push(...ingredient);
  }
}

Person Clicks ToShopping List Output of Shopping List

1 answer

  • answered 2019-10-15 17:41 Jibi Abraham

    I'm assuming your Ingredients model has a way to retrieve the name and quantity of an ingredient. Something like

    const apples = new Ingredients('Apple',10);
    
    apples.name; // should return 'Apple'
    apples.quantity; // should return 10
    
    apples.quantity = 15; // should set the quantity to 15
    apples.quantity; // should now return 15
    

    In which case, the simplest solution would be to check if an ingredient exists in your array before adding it. Something like

    function toShoppingList(ingredients = []) {
        const list = [];
        for (const ingredient of ingredients) {
            const { name, quantity } = ingredient;
            const existingIngredient = list.filter(item => item.name === name)[0];
            if (existingIngredient) {
                existingIngredient.quantity += quantity;
            } else {
                list.push(new Ingredients(name, quantity));
            }
        }
        return list;
    }