Compare array of object values if equals add it total

Tags: , ,



    [{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.

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)


Source: stackoverflow