PAYATHON 2026

如何在 python 中按食材和单位合并多个食谱的用量?

技术老齐

可以用字典累加用量,以 (食材名称, 单位) 元组作为键。名称和单位都相同的条目会合并;同一种食材如果使用不同单位,则分别保留。

例如,("番茄", "克") 的用量可以累加,("黄瓜", "根") 和 ("黄瓜", "克") 则会保存在不同的键下。

先把食材整理成结构化数据

从网页抓取数据后,先把每条记录拆成食材名称、单位和数值用量三个字段,避免在求和时再处理 "500 克番茄" 这样的整段文本。

每条记录用一个元组表示,字段顺序固定为 (名称, 单位, 用量):

recipe_1 = [
    ("番茄", "克", 500),
    ("橄榄油", "dl", 1),
    ("黄瓜", "根", 2),
]

recipe_2 = [
    ("牛油果", "个", 2),
    ("番茄", "克", 200),
    ("橄榄油", "dl", 1),
    ("黄瓜", "克", 100),
]

按名称和单位累加

遍历所有食谱,用每条记录的 (name, unit) 作为键。键已存在时,加上本次用量;首次遇到时,从 0 开始累加。

def merge_recipes(recipes):
    totals = {}

    for recipe in recipes:
        for name, unit, amount in recipe:
            key = (name, unit)
            totals[key] = totals.get(key, 0) + amount

    return totals


shopping_list = merge_recipes([recipe_1, recipe_2])

for (name, unit), amount in shopping_list.items():
    print(f"{amount} {unit} {name}")

把这段代码接在前面的数据后运行,输出为:

700 克 番茄
2 dl 橄榄油
2 根 黄瓜
2 个 牛油果
100 克 黄瓜

读取当前累计用量的是:

totals.get(key, 0)

如果字典中还没有这个键,它会返回默认值 0。

Python 3.7 及以上版本的字典保证保留插入顺序,因此结果会按每个食材与单位组合首次出现的顺序输出,后续累加不会改变其位置。

处理抓取数据时的注意事项

统一名称和单位的写法

字典按键的实际值分组,不会自动识别同义词。例如,"番茄" 和 "西红柿" 会被当作两种食材,"克" 和 "g" 也会被当作两种单位。

如果数据源混用了这些写法,可以先用映射表统一:

name_aliases = {
    "西红柿": "番茄",
}

unit_aliases = {
    "g": "克",
    "grams": "克",
}

在生成 key 之前,先处理名称和单位:

name = name.strip()
unit = unit.strip()

name = name_aliases.get(name, name)
unit = unit_aliases.get(unit, unit)

key = (name, unit)

映射规则要根据抓取的数据确定,避免误合并实际不同的食材。

将用量转换为数值

示例中的 amount 已经是整数。如果抓到的是 "500" 这样的字符串,应在整理数据时将它转换成数值。

"1/2"、"半根" 或 "适量" 需要单独制定解析规则。其中,“适量”没有可直接相加的数值,可以保留为备注。

需要精确累加十进制小数时,可以使用 Decimal,并从字符串构造,例如 Decimal("0.1"),避免先转换为 float 带来的误差。

单位换算需要另外处理

上面的函数只合并单位完全相同的条目。"千克" 和 "克" 虽然都表示重量,仍会分别保留。要合并它们,需要先将用量换算到统一单位,并更新单位字段。

仅凭“根”和“克”无法确定换算关系,因此将黄瓜保留为两条记录符合题目要求。

备注:内容仅供参考。