You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ReactJS实现数组重复食材合并与数量求和

合并重复食材并累加数量的实现方案

需求:遍历数组时合并重复食材(如示例中的切达奶酪),仅显示一次并累加其数量。现有代码可正常运行,但重复食材会多次显示,以下是修改方案:

现有代码

分类处理代码

const categorizedDataFoods12 = listUserM.reduce((acc, curr) => {
    const { id, Category, Foods } = curr;
    if (!acc[Category]) {
      acc[Category] = {
        items: [],
      };
    }
    acc[Category].items.push({ id, Category, Foods });
    return acc;
  }, {});

遍历渲染代码

{categorizedDataFoods12[key]?.items
    .map((checkbox, index) => {
    const data4food = checkbox.Foods
    const d4f = data4food.map((d) =>

示例数据源

{
    "items": [
        {
            "id": "biuBOoxw8Jxn9PPmyBKu",
            "Category": "LUNCH",
            "Foods": [
                {
                    "value": "Vita-Weat (pack)",
                    "label": "Vita-Weat (pack)",
                    "id": "ynBBDaX807LUa0093fJm",
                    "Weight": "0.312",
                    "Quantity": "0.50"
                },
                {
                    "Quantity": 1,
                    "value": "Coppa (200g)",
                    "Weight": "0.200",
                    "id": "meyqfO8dxmNrx19EV86o",
                    "label": "Coppa (200g)"
                },
                {
                    "id": "74b67090-15da-11ec-b278-b1ac8c1941a3",
                    "Weight": 0.25,
                    "label": "Cheddar Cheese (250g)",
                    "Quantity": "0.50",
                    "value": "Cheddar Cheese (250g)"
                },
                {
                    "value": "Cherry Tomatoes (punnet)",
                    "label": "Cherry Tomatoes (punnet)",
                    "Quantity": "0.50",
                    "id": "74c64f10-15da-11ec-b278-b1ac8c1941a3",
                    "Weight": 0.28
                },
                {
                    "id": "74d5df70-15da-11ec-b278-b1ac8c1941a3",
                    "label": "Lebanese Cucumbers",
                    "Quantity": 1,
                    "value": "Lebanese Cucumbers",
                    "Weight": 0.17
                },
                {
                    "value": "Pickled Onions",
                    "id": "qSiC2ZR8v976QBzd0HTh",
                    "Quantity": "3.00",
                    "label": "Pickled Onions",
                    "Weight": ""
                }
            ]
        },
        {
            "id": "PodfQqRU3UOFKq4QX26q",
            "Category": "LUNCH",
            "Foods": [
                {
                    "id": "ynBBDaX807LUa0093fJm",
                    "value": "Vita-Weat (pack)",
                    "Weight": "0.312",
                    "label": "Vita-Weat (pack)",
                    "Quantity": "0.50"
                },
                {
                    "Weight": 0.25,
                    "label": "Cheddar Cheese (250g)",
                    "Quantity": "0.50",
                    "id": "74b67090-15da-11ec-b278-b1ac8c1941a3",
                    "value": "Cheddar Cheese (250g)"
                },
                {
                    "id": "74c64f10-15da-11ec-b278-b1ac8c1941a3",
                    "label": "Cherry Tomatoes (punnet)",
                    "Weight": 0.28,
                    "Quantity": "0.50",
                    "value": "Cherry Tomatoes (punnet)"
                },
                {
                    "Quantity": 1,
                    "id": "74d5df70-15da-11ec-b278-b1ac8c1941a3",
                    "value": "Lebanese Cucumbers",
                    "Weight": 0.17,
                    "label": "Lebanese Cucumbers"
                },
                {
                    "label": "Pickled Onions",
                    "Weight": "",
                    "id": "qSiC2ZR8v976QBzd0HTh",
                    "value": "Pickled Onions",
                    "Quantity": "3.00"
                }
            ]
        },
        {
            "id": "ukZv9L19IHwIk4QRs0Aq",
            "Category": "LUNCH",
            "Foods": [
                {
                    "value": "Ham",
                    "Weight": 0.176,
                    "label": "Ham",
                    "Quantity": "1.00"
                },
                {
                    "Weight": 0.59,
                    "id": "76fd7a60-15da-11ec-b278-b1ac8c1941a3",
                    "label": "Wraps (8 pack)",
                    "Quantity": "0.25",
                    "value": "Wraps (8 pack)"
                },
                {
                    "Quantity": "0.50",
                    "label": "Cheddar Cheese (250g)",
                    "id": "74b67090-15da-11ec-b278-b1ac8c1941a3",
                    "Weight": 0.25,
                    "value": "Cheddar Cheese (250g)"
                },
                {
                    "id": "74d5df70-15da-11ec-b278-b1ac8c1941a3",
                    "Weight": 0.17,
                    "value": "Lebanese Cucumbers",
                    "label": "Lebanese Cucumbers",
                    "Quantity": 1
                },
                {
                    "Quantity": "0.50",
                    "id": "74c64f10-15da-11ec-b278-b1ac8c1941a3",
                    "value": "Cherry Tomatoes (punnet)",
                    "Weight": 0.28,
                    "label": "Cherry Tomatoes (punnet)"
                }
            ]
        },
        {
            "id": "BGS8QUqy8bMoTgA61bgf",
            "Category": "LUNCH",
            "Foods": [
                {
                    "label": "Wraps (8 pack)",
                    "value": "Wraps (8 pack)",
                    "Quantity": "0.30",
                    "id": "76fd7a60-15da-11ec-b278-b1ac8c1941a3",
                    "Food": "",
                    "Weight": 0.59
                },
                {
                    "value": "Coppa (200g)",
                    "Weight": "0.200",
                    "Quantity": "0.25",
                    "label": "Coppa (200g)",
                    "id": "meyqfO8dxmNrx19EV86o"
                },
                {
                    "label": "Cheddar Cheese (250g)",
                    "value": "Cheddar Cheese (250g)",
                    "id": "74b67090-15da-11ec-b278-b1ac8c1941a3",
                    "Weight": 0.25,
                    "Quantity": "0.50"
                },
                {
                    "id": "74c64f10-15da-11ec-b278-b1ac8c1941a3",
                    "Quantity": "0.50",
                    "value": "Cherry Tomatoes (punnet)",
                    "label": "Cherry Tomatoes (punnet)",
                    "Weight": 0.28
                },
                {
                    "id": "74d5df70-15da-11ec-b278-b1ac8c1941a3",
                    "Quantity": 1,
                    "value": "Lebanese Cucumbers",
                    "Weight": 0.17,
                    "label": "Lebanese Cucumbers"
                }
            ]
        }
    ]
}

修改后的实现代码

分类合并食材的逻辑

const categorizedDataFoods12 = listUserM.reduce((acc, curr) => {
  const { Category, Foods } = curr;
  if (!acc[Category]) {
    acc[Category] = {
      items: {}, // 用对象按食材id分组存储合并数据
    };
  }

  Foods.forEach(food => {
    const foodId = food.id;
    // 转换Quantity为数字,避免字符串拼接错误
    const quantity = parseFloat(food.Quantity) || 0;

    if (acc[Category].items[foodId]) {
      // 累加数量,保留两位小数
      acc[Category].items[foodId].Quantity = (parseFloat(acc[Category].items[foodId].Quantity) + quantity).toFixed(2);
    } else {
      // 首次出现,复制原食材属性并格式化数量
      acc[Category].items[foodId] = {
        ...food,
        Quantity: quantity.toFixed(2),
      };
    }
  });

  // 将分组对象转为数组,方便后续遍历渲染
  acc[Category].items = Object.values(acc[Category].items);
  return acc;
}, {});

简化后的遍历渲染

{categorizedDataFoods12[key]?.items.map((food, index) => (
  <div key={food.id}>
    {food.label} - 累计数量: {food.Quantity}
  </div>
))}

关键说明

  • 用食材的id作为唯一标识,确保相同食材被正确合并(比label/value更可靠,避免名称差异导致的误判)
  • 统一将Quantity转为数字计算,防止字符串拼接错误,最后用toFixed(2)保留两位小数
  • 最终将分组对象转为数组,保持和原代码类似的遍历方式,无需大幅修改渲染逻辑

内容的提问来源于stack exchange,提问作者Paul VI

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 07:08:09