Home > OS >  Javascript - Combine arrays and add to value
Javascript - Combine arrays and add to value

Time:10-17

I'm trying to do a shopping list generator (client selects cocktails and an ingredients list is generated) and I'm just stuck on this part. I have the following code:

There's a 'data' set which contains the arrays for all the cocktails and their ingredients but it's too big to paste here. 'savedData' is the selected cocktails ingredients.

function loadData(savedData) {
    let selectedCocktailsHTML = ``;
    savedData.cocktailsList.forEach(item => {
        let selectedIngredients = ``;
        if (item.isChecked) {
            item.ingredients.forEach(ingred => {
                selectedIngredients  = `<p>${ingred.name} - ${ingred.selectedQty} ${ingred.capacity}</p>`;
            });
            selectedCocktailsHTML  = `<p > ${selectedIngredients}`;
        }
    });

And it gives me an output like this:

Vodka - 1 bottles 1L

Peach Schnapps - 1 bottles 1L

Cranberry Juice - 2 bottles 1L

Coffee Liqueur - 1 bottles 1L

Vodka - 1 bottles 1L

What I would like to do is to loop through and combine the duplicate values when the user selects them (such as vodka in this case) and then add the quantities of each one together. My desired output for this example would be:

Vodka - 2 bottles 1L

Peach Schnapps - 1 bottles 1L

Cranberry Juice - 2 bottles 1L

Coffee Liqueur - 1 bottles 1L

Can anyone help with the best way to go about this? Theres a lot of the code I didn't add, let me know if you need more to work it out.

CodePudding user response:

I'm not sure how's your savedData struct look like, but if you want combine the same product's quantities. I will do like this:

//loadData function
function loadData(savedData) {
    let selectedCocktailsHTML = ``;
    let ingredientsInfo = {};
    savedData.cocktailsList.forEach(item => {
        if (item.isChecked) {
            item.ingredients.forEach(ingred => {
                if(!ingredientsInfo[ingred.name]){
                    ingredientsInfo[ingred.name] = {
                        capacity:ingred.capacity,
                        count:1
                    };
                }
                else{
                    ingredientsInfo[ingred.name].count  ;
                }
            });
        }
    });
    for(let i = 0; i < Object.keys(ingredientsInfo).length; i  ){
        let name = Object.keys(ingredientsInfo)[i];
        let count = ingredientsInfo[name].count;
        let capacity = ingredientsInfo[name].capacity;
        let selectedIngredients = `<p>${name} - ${count} ${capacity}</p>`;
        selectedCocktailsHTML  = `<p > ${selectedIngredients}`;
    }
    return selectedCocktailsHTML;
}

//function test
loadData({
    cocktailsList:[
        {
            ingredients:[
                {
                    name:"Vodka",
                    selectedQty:1,
                    capacity:"bottles 1L"
                }
            ],
            isChecked:true
        },
        {
            ingredients:[
                {
                    name:"Vodka",
                    selectedQty:1,
                    capacity:"bottles 1L"
                }
            ],
            isChecked:true
        }
    ]
});

Is this what you want?

CodePudding user response:

Rather than a forEach over the cocktailsList I would use reduce to add all the quantities of each ingredient into an object. Then you can build the result HTML from iterating that object:

cocktails = { cocktailsList: [
  { ingredients : [ 
    { name : 'Vodka', capacity : '1L', selectedQty : 1 },
    { name : 'Peach Schnapps', capacity : '1L', selectedQty : 1 },
    { name : 'Cranberry Juice', capacity : '1L', selectedQty : 2 }
  ], 
    isChecked : 1
  },
    { ingredients : [ 
    { name : 'Coffee Liqueur', capacity : '1L', selectedQty : 1 },
    { name : 'Vodka', capacity : '1L', selectedQty : 1 }
  ], 
    isChecked : 1
  }
  ]
}

function loadData(savedData) {
  const ingreds = savedData.cocktailsList.reduce((acc, item) => {
    if (item.isChecked) {
      item.ingredients.forEach(ingred => {
        key = `${ingred.name} - ${ingred.capacity}`
        acc[key] = (acc[key] || 0)   ingred.selectedQty
      })
    }
    return acc
  }, {})
  return '<p >'   
    Object.entries(ingreds).map(([k, v]) => {
      [name, capacity] = k.split(' - ')
      return `<p>${name} - ${v} bottles ${capacity}</p>`
    }).join('')
}

document.write(loadData(cocktails))

  • Related