JavaScript
x
9
1
[{ingName: "egg", quantity: "2.0", unit: "pcs"},
2
{ingName: "water", quantity: "0.03", unit: "l"},
3
{ingName: "salt", quantity: "1.0", unit: "pinch"}],
4
5
[{ingName: "egg", quantity: "2.0", unit: "pcs"},
6
{ingName: "water", quantity: "0.03", unit: "l"},
7
{ingName: "salt", quantity: "1.0", unit: "pinch"},
8
{ingName: "olive oil", quantity: "2.0", unit: "tablespoons"]
9
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.
JavaScript
1
9
1
<button
2
value={item.id}
3
onClick={(e) => {setMenu([menu,{name:item.name,ingredients:item.ingredients}])}}
4
className="btn-xs btn-light"
5
type="button"
6
>
7
Make {item.name}
8
</button>
9
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
JavaScript
1
2
1
total : egg 4pcs , water 0.06 l , salt 2.0 pinch , olive oil 2.0 tablespoons
2
I tried this :
JavaScript
1
2
1
menu.map(item => item.ingredients).map((x,index)=> console.log(x[index].ingName))
2
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.
JavaScript
1
46
46
1
const ingredientFunc = (input1,input2) => {
2
const output = input1.reduce(
3
(acc, input) => {
4
const matchedItem =
5
input2.length > 0 &&
6
input2.find((item) => item.ingName === input.ingName);
7
if (matchedItem) {
8
const updatedItem = {
9
ingName: input.ingName,
10
quantity: Number(input.quantity) + Number(matchedItem.quantity),
11
unit: input.unit,
12
};
13
acc.item.push(updatedItem);
14
acc.toFilter.push(matchedItem.ingName);
15
} else {
16
acc.item.push(input);
17
}
18
return acc;
19
},
20
{ item: [], toFilter: [] }
21
);
22
23
const filteredOutput = input2.filter(
24
(item) => !output.toFilter.includes(item.ingName)
25
);
26
const totalValues = [output.item, filteredOutput];
27
setTotal(totalValues);
28
}
29
30
React.useEffect(() => {
31
if(menu.length === 1 ){
32
setTotal(menu[0].ingredients);
33
}
34
if(menu.length === 2){
35
const input1 = menu[0].ingredients;
36
const input2 = menu[1].ingredients;
37
ingredientFunc(input1,input2)
38
}
39
if(menu.length >= 3){
40
const input1 = total;
41
const input2 = menu[indexCount].ingredients;
42
ingredientFunc(input1,input2);
43
}
44
45
},[menu.length,indexCount]);
46
And modified button
JavaScript
1
13
13
1
<button
2
value={item.id}
3
onClick={(e) => {
4
setMenu([
5
menu,
6
{ name: item.name, ingredients: item.ingredients },
7
]);
8
setCount(indexCount+1);
9
}}
10
className="btn-xs btn-light"
11
type="button"
12
>
13
Used indexCount state to locate last added recipe’s index.
Advertisement
Answer
JavaScript
1
61
61
1
const input1 = [{ingName: "egg", quantity: "2.0", unit: "pcs"},
2
{ingName: "water", quantity: "0.03", unit: "l"},
3
{ingName: "salt", quantity: "1.0", unit: "pinch"}];
4
5
const input2 = [{ingName: "egg", quantity: "2.0", unit: "pcs"},
6
{ingName: "water", quantity: "0.03", unit: "l"},
7
{ingName: "salt", quantity: "1.0", unit: "pinch"},
8
{ingName: "olive oil", quantity: "2.0", unit: "tablespoons"}];
9
10
11
const output = input1.reduce((acc,input) => {
12
const matchedItem = input2.length > 0 && input2.find(item => item.ingName === input.ingName);
13
if(matchedItem){
14
const updatedItem = {
15
ingName: input.ingName,
16
quantity: Number(input.quantity) + Number(matchedItem.quantity),
17
unit: input.unit
18
}
19
acc.item.push(updatedItem);
20
acc.toFilter.push(matchedItem.ingName)
21
} else {
22
acc.item.push(input)
23
}
24
25
return acc;
26
}, {item:[] , toFilter: []});
27
28
29
const getFinalReceipes = (input1, input2) => {
30
const output = input1.reduce((acc,input) => {
31
const matchedItem = input2.length > 0 && input2.find(item => item.ingName === input.ingName);
32
if(matchedItem){
33
const updatedItem = {
34
ingName: input.ingName,
35
quantity: Number(input.quantity) + Number(matchedItem.quantity),
36
unit: input.unit
37
}
38
acc.item.push(updatedItem);
39
acc.toFilter.push(matchedItem.ingName)
40
} else {
41
acc.item.push(input)
42
}
43
44
return acc;
45
}, {item:[] , toFilter: []});
46
47
const filteredOutput = input2.filter(item => !output.toFilter.includes(item.ingName));
48
49
const totalValues = [output.item, filteredOutput];
50
51
return totalValues;
52
53
}
54
55
const mergedReceipes1And2 = getFinalReceipes(input1, input2);
56
57
// Pass the merged result as the first argument
58
const mergedReceipe3 = getFinalReceipes(mergedReceipes1And2, [{ingName: "sugar", quantity: "1.0", unit: "pinch"}])
59
60
61
console.log(mergedReceipe3)