[{ingName: "egg", quantity: "2.0", unit: "pcs"}, {ingName: "water", quantity: "0.03", unit: "l"}, {ingName: "salt", quantity: "1.0", unit: "pinch"}], [{ingName: "egg", quantity: "2.0", unit: "pcs"}, {ingName: "water", quantity: "0.03", unit: "l"}, {ingName: "salt", quantity: "1.0", unit: "pinch"}, {ingName: "olive oil", quantity: "2.0", unit: "tablespoons"]
I have an array structure as above in my app whenever user clicks make pizza or another recipe it adding recipe informations to new menu state given below.
<button value={item.id} onClick={(e) => {setMenu([...menu,{name:item.name,ingredients:item.ingredients}])}} className="btn-xs btn-light" type="button" > Make {item.name} </button>
After that i need to compare that menu array’s ingName and unit fields to calculate total ingredient need for ex. according to above array total is like
total : egg 4pcs , water 0.06 l , salt 2.0 pinch , olive oil 2.0 tablespoons
I tried this :
menu.map(item => item.ingredients).map((x,index)=> console.log(x[index].ingName))
it gets ingName property but after that i stuck.Thanks for help.
Edit :
React Solution : First declared Shyam’s solution as function and used useeffect hook for to calculate total ingredients when user clicks button, useeffect updating total array.
const ingredientFunc = (input1,input2) => { const output = input1.reduce( (acc, input) => { const matchedItem = input2.length > 0 && input2.find((item) => item.ingName === input.ingName); if (matchedItem) { const updatedItem = { ingName: input.ingName, quantity: Number(input.quantity) + Number(matchedItem.quantity), unit: input.unit, }; acc.item.push(updatedItem); acc.toFilter.push(matchedItem.ingName); } else { acc.item.push(input); } return acc; }, { item: [], toFilter: [] } ); const filteredOutput = input2.filter( (item) => !output.toFilter.includes(item.ingName) ); const totalValues = [...output.item, ...filteredOutput]; setTotal(totalValues); } React.useEffect(() => { if(menu.length === 1 ){ setTotal(menu[0].ingredients); } if(menu.length === 2){ const input1 = menu[0].ingredients; const input2 = menu[1].ingredients; ingredientFunc(input1,input2) } if(menu.length >= 3){ const input1 = total; const input2 = menu[indexCount].ingredients; ingredientFunc(input1,input2); } },[menu.length,indexCount]);
And modified button
<button value={item.id} onClick={(e) => { setMenu([ ...menu, { name: item.name, ingredients: item.ingredients }, ]); setCount(indexCount+1); }} className="btn-xs btn-light" type="button" >
Used indexCount state to locate last added recipe’s index.
Advertisement
Answer
const input1 = [{ingName: "egg", quantity: "2.0", unit: "pcs"}, {ingName: "water", quantity: "0.03", unit: "l"}, {ingName: "salt", quantity: "1.0", unit: "pinch"}]; const input2 = [{ingName: "egg", quantity: "2.0", unit: "pcs"}, {ingName: "water", quantity: "0.03", unit: "l"}, {ingName: "salt", quantity: "1.0", unit: "pinch"}, {ingName: "olive oil", quantity: "2.0", unit: "tablespoons"}]; const output = input1.reduce((acc,input) => { const matchedItem = input2.length > 0 && input2.find(item => item.ingName === input.ingName); if(matchedItem){ const updatedItem = { ingName: input.ingName, quantity: Number(input.quantity) + Number(matchedItem.quantity), unit: input.unit } acc.item.push(updatedItem); acc.toFilter.push(matchedItem.ingName) } else { acc.item.push(input) } return acc; }, {item:[] , toFilter: []}); const getFinalReceipes = (input1, input2) => { const output = input1.reduce((acc,input) => { const matchedItem = input2.length > 0 && input2.find(item => item.ingName === input.ingName); if(matchedItem){ const updatedItem = { ingName: input.ingName, quantity: Number(input.quantity) + Number(matchedItem.quantity), unit: input.unit } acc.item.push(updatedItem); acc.toFilter.push(matchedItem.ingName) } else { acc.item.push(input) } return acc; }, {item:[] , toFilter: []}); const filteredOutput = input2.filter(item => !output.toFilter.includes(item.ingName)); const totalValues = [...output.item, ...filteredOutput]; return totalValues; } const mergedReceipes1And2 = getFinalReceipes(input1, input2); // Pass the merged result as the first argument const mergedReceipe3 = getFinalReceipes(mergedReceipes1And2, [{ingName: "sugar", quantity: "1.0", unit: "pinch"}]) console.log(mergedReceipe3)