如何使用array.reduce()处理嵌套数组并计算食材总用量?
用*Array.reduce()*汇总嵌套订单中的食材用量
原始订单数据
const 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" } ] } ] }];
期望结果
计算每个食材的总用量(食材单份用量 × 对应商品的订购数量),最终得到:
const 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" } ];
实现思路与代码解析
1. 先搞懂*Array.reduce()*的核心逻辑
reduce是用来将数组元素逐步合并为单一结果的方法,基本语法:
array.reduce((accumulator, currentValue) => { // 处理逻辑,返回更新后的累加器 }, initialValue);
accumulator:累加器,存储中间计算结果,每次回调都会更新它currentValue:当前遍历到的数组元素initialValue:累加器的初始值(这里用空对象{}来存储食材的汇总数据)
2. 遍历嵌套结构+汇总逻辑
我们需要逐层遍历订单数据,同时用reduce的累加器来去重并累加食材用量:
// 用reduce汇总食材 const ingredientMap = orders.reduce((acc, order) => { // 遍历当前订单的所有商品 order.line_items.forEach(item => { // 遍历当前商品的所有食材 item.recipe.forEach(ing => { // 计算当前食材的总用量:单份用量 × 商品订购数量 const calculatedQty = parseInt(ing.ing_qty) * item.item_qty; // 检查累加器中是否已有该食材 if (acc[ing.ing_name]) { // 已有则累加数量,最后转回字符串格式 acc[ing.ing_name].ing_qty = (parseInt(acc[ing.ing_name].ing_qty) + calculatedQty).toString(); } else { // 没有则新增条目 acc[ing.ing_name] = { ing_name: ing.ing_name, ing_qty: calculatedQty.toString(), ing_unit: ing.ing_unit }; } }); }); // 返回更新后的累加器 return acc; }, {}); // 初始值为空白对象 // 将对象转换为数组,得到最终结果 const total_ingredients = Object.values(ingredientMap);
3. 代码拆解
- 外层
orders.reduce()遍历所有订单,用空对象作为初始累加器 - 内层嵌套
forEach,分别遍历订单下的商品、商品下的食材 - 对每个食材计算总用量,通过累加器对象实现同名食材的数量合并
- 最后用
Object.values()将累加器对象转换为数组,匹配期望的输出格式
内容的提问来源于stack exchange,提问作者Joseph P
相关产品推荐
相关产品推荐

