Skip to content
Advertisement

Looping through and reducing nested array

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
})
User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement