I can’t seem to get my head around the array.reduce() function. I’ve got the following array:
orders = [{ "id": 4930, "status": "pending", "line_items": [ { "item_name": "Crepe", "item_qty": 2, "recipe": [ { "ing_name": "Flour", "ing_qty": "120", "ing_unit": "g" }, { "ing_name": "Milk", "ing_qty": "100", "ing_unit": "ml" }, { "ing_name": "Egg", "ing_qty": "2", "ing_unit": "each" } ] }, { "item_name": "Pancake", "item_qty": 3, "recipe": [ { "ing_name": "Flour", "ing_qty": "120", "ing_unit": "g" }, { "ing_name": "Milk", "ing_qty": "100", "ing_unit": "ml" }, { "ing_name": "Egg", "ing_qty": "2", "ing_unit": "each" }, { "ing_name": "Sugar", "ing_qty": "10", "ing_unit": "g" } ] } ] }, { "id": 4927, "status": "pending", "line_items": [ { "item_name": "Pancake", "item_qty": 2, "recipe": [ { "ing_name": "Flour", "ing_qty": "120", "ing_unit": "g" }, { "ing_name": "Milk", "ing_qty": "100", "ing_unit": "ml" }, { "ing_name": "Egg", "ing_qty": "2", "ing_unit": "each" }, { "ing_name": "Sugar", "ing_qty": "10", "ing_unit": "g" } ] } ] }];
and I’m trying to get a result like below. I’m not sure how to go about multiplying the ingredient amounts with the item quantities:
"total_ingredients": [{ "ing_name": "Flour", "ing_qty": "840", "ing_unit": "g" }, { "ing_name": "Milk", "ing_qty": "700", "ing_unit": "ml" }, { "ing_name": "Egg", "ing_qty": "14", "ing_unit": "each" }, { "ing_name": "Sugar", "ing_qty": "20", "ing_unit": "g" } ];
I’ve tried following the structure that was given here but the arrow function is throwing me off. Any sort of help would be greatly appreciated.
Advertisement
Answer
Read about reduce. It’s awesome. About this one, let me explain.
We start with this skeleton, preparing to group by some property:
orders.reduce(function(agg, order) { agg[order["some_property"]] = order; return agg; }, {})
That’s the idea!
Anyway, for each of these, we iterate the list of recipes and products, with the idea to collect instead of “some_property” the actual “ing_name”. While we group, we calculate the total. Finally, Object.values() will remove the keys we grouped by and turn it into the required array.
var orders = [{ "id": 4930, "status": "pending", "line_items": [{ "item_name": "Crepe", "item_qty": 2, "recipe": [{ "ing_name": "Flour", "ing_qty": "120", "ing_unit": "g" }, { "ing_name": "Milk", "ing_qty": "100", "ing_unit": "ml" }, { "ing_name": "Egg", "ing_qty": "2", "ing_unit": "each" } ] }, { "item_name": "Pancake", "item_qty": 3, "recipe": [{ "ing_name": "Flour", "ing_qty": "120", "ing_unit": "g" }, { "ing_name": "Milk", "ing_qty": "100", "ing_unit": "ml" }, { "ing_name": "Egg", "ing_qty": "2", "ing_unit": "each" }, { "ing_name": "Sugar", "ing_qty": "10", "ing_unit": "g" } ] } ] }, { "id": 4927, "status": "pending", "line_items": [{ "item_name": "Pancake", "item_qty": 2, "recipe": [{ "ing_name": "Flour", "ing_qty": "120", "ing_unit": "g" }, { "ing_name": "Milk", "ing_qty": "100", "ing_unit": "ml" }, { "ing_name": "Egg", "ing_qty": "2", "ing_unit": "each" }, { "ing_name": "Sugar", "ing_qty": "10", "ing_unit": "g" } ] }] } ]; total_ingredients = Object.values(orders.reduce(function(agg, order) { order.line_items.forEach(function(item) { item.recipe.forEach(function(product) { agg[product.ing_name] = agg[product.ing_name] || { ing_name: product.ing_name, ing_qty: 0, ing_unit: product.ing_unit } agg[product.ing_name].ing_qty = Number(agg[product.ing_name].ing_qty) + Number(product.ing_qty) }) }) return agg; }, {})) console.log({ total_ingredients: total_ingredients })