1

New to Javascript. Have been at this for hours looking at examples, but I can't seem to get my head around it.

I have an array of objects with nested properties that I'm trying to loop through and consolidate.

var items = [{
        name: "flat bread",
        price: "5",
        components: [
            { qty: 120, unit: "g", ingredient: { name: "flour", price: 1, perAmount: 1, unit: "kg" } },
            { qty: 250, unit: "mL", ingredient: { name: "milk", price: 4, perAmount: 3, unit: "litre" } },
            { qty: 1.5, unit: "g", ingredient: { name: "salt", price: 1.2, perAmount: 1, unit: "kg" } },
            { qty: 28.35, unit: "g", ingredient: { name: "butter", price: "6", perAmount: 500, unit: "g" } }
        ]
    },
    {
        name: "pancake",
        price: "15",
        components: [
            { qty: 120, unit: "g", ingredient: { name: "flour", price: 1, perAmount: 1, unit: "kg" } },
            { qty: 250, unit: "mL", ingredient: { name: "milk", price: 4, perAmount: 3, unit: "litre" } },
            { qty: 2, unit: "each", ingredient: { name: "egg", price: 5, perAmount: 12, unit: "each" } },
            { qty: 12.5, unit: "g", ingredient: { name: "sugar", price: 2.20, perAmount: 2, unit: "kg" } }
        ]
    },
    {
        name: "crepe",
        price: "10",
        components: [
            { qty: 120, unit: "g", ingredient: { name: "flour", price: 1, perAmount: 1, unit: "kg" } },
            { qty: 250, unit: "mL", ingredient: { name: "milk", price: 4, perAmount: 3, unit: "litre" } },
            { qty: 2, unit: "each", ingredient: { name: "egg", price: 5, perAmount: 12, unit: "each" } },
            { qty: 28.35, unit: "g", ingredient: { name: "butter", price: "6", perAmount: 500, unit: "g" } }
        ]
    }
];


consolidatedComponents = items.map((item) => {
    return { components: item.components }
});
console.log(consolidatedComponents);

I'm trying to get a result like this to return:

  • 360g flour
  • 750ml milk
  • 1.5g salt 4 eggs
  • 12.5g sugar
  • 56.7g butter

I realise I will need to convert the units down the track, but let's assume they are all the same across the items/ingredients

4
  • do you have always same units for ingrediences? Commented Jul 23, 2022 at 8:42
  • Yes. Let's assume they are always the same for now. I just want to focus on consolidating the components Commented Jul 23, 2022 at 8:45
  • btw, what result do you expect (data structure)? Commented Jul 23, 2022 at 8:47
  • @NinaScholz the structure you have provided in your answer is perfect. I'm looking into the reduce method right now to try and understand exactly how your code works just to make sure there won't be any problems Commented Jul 23, 2022 at 9:03

1 Answer 1

1

You could take an object to collect all items grouped by ingredient.

If you like to get a list, iterate the object.

const
    items = [{ name: "flat bread", price: "5", components: [{ qty: 120, unit: "g", ingredient: { name: "flour", price: 1, perAmount: 1, unit: "kg" } }, { qty: 250, unit: "mL", ingredient: { name: "milk", price: 4, perAmount: 3, unit: "litre" } }, { qty: 1.5, unit: "g", ingredient: { name: "salt", price: 1.2, perAmount: 1, unit: "kg" } }, { qty: 28.35, unit: "g", ingredient: { name: "butter", price: "6", perAmount: 500, unit: "g" } }] }, { name: "pancake", price: "15", components: [{ qty: 120, unit: "g", ingredient: { name: "flour", price: 1, perAmount: 1, unit: "kg" } }, { qty: 250, unit: "mL", ingredient: { name: "milk", price: 4, perAmount: 3, unit: "litre" } }, { qty: 2, unit: "each", ingredient: { name: "egg", price: 5, perAmount: 12, unit: "each" } }, { qty: 12.5, unit: "g", ingredient: { name: "sugar", price: 2.20, perAmount: 2, unit: "kg" } }] }, { name: "crepe", price: "10", components: [{ qty: 120, unit: "g", ingredient: { name: "flour", price: 1, perAmount: 1, unit: "kg" } }, { qty: 250, unit: "mL", ingredient: { name: "milk", price: 4, perAmount: 3, unit: "litre" } }, { qty: 2, unit: "each", ingredient: { name: "egg", price: 5, perAmount: 12, unit: "each" } }, { qty: 28.35, unit: "g", ingredient: { name: "butter", price: "6", perAmount: 500, unit: "g" } }] }],
    consolidatedComponents = items.reduce((r, { components }) => {
        components.forEach(({ qty, unit, ingredient: { name } }) => {
            r[name] ??= { unit, qty: 0 };
            r[name].qty += qty;        
        });
        return r;
    }, {});
    
console.log(consolidatedComponents);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Sign up to request clarification or add additional context in comments.

3 Comments

The way you spun that together in 5 minutes blows my mind. I have never seen the " ??= " operator before so I'm going to read into that, thank you
Thank you for this. This has lead me to read about the reduce() method and also the arrow function. I have so much left to learn!
Updated solution can be found here: stackoverflow.com/questions/73093137/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.