如何使用用户的输入作为嵌套字典中的键来搜索字典?

问题描述 投票:0回答:1

正在从事 cs50 Python 编程简介的最终项目。尝试实现具有一些功能的程序,例如:计算基础代谢率、格式化产品列表、打印用户指定产品的营养价值以及根据用户指定的大量营养素按产品价值建议/排序产品。

后一个功能遇到问题。

我对不同产品及其营养价值有一个两级深度字典,例如 - 香蕉:

products = {"banana": {"protein": 1.3, "fat": 0.4, "carbs": 27.0, "fiber": 3.1, "calories": 105}}

我想实现一个功能,要求用户提供常量营养素(蛋白质、脂肪、碳水化合物、纤维或卡路里 - 所有这些都是嵌套字典的键),搜索产品字典,然后输出前三个产品,基于根据用户指定的营养价值。

我无法按字典的值对它进行排序(正如我所见)。考虑将值存储为嵌套列表:

products = {"banana": [1.3, 0.4, 27.0, 3.1, 105]}

所以我可以通过以下方式调用一个值:

product = input("Name of a product: ").lower().strip()
macro = input("Name of a macronutrient: ").lower().strip()
# using macro variable and if statements to specify the index of a list
if macro == "protein":
    products.keys(product)[0] # running into a problem when calling product here

但无论如何,产品字典似乎有点神秘,所以我想避免这个选项。

目前我有以下功能:

def _get_nested_val(data, *args):
    if args and data:
        element  = args[0]
        if element:
            value = data.get(element)
            return value if len(args) == 1 else _get_nested_val(value, *args[1:])

我在 main() 中调用此函数,用于向用户展示特定产品的营养价值:

    elif initial == "show specifics":
            product = input("Enter a name of the product: ").lower().strip()
            call = input("Enter a macronutrient: ").lower().strip()
            if call == "protein" or call == "fat" or call == "carbs" or call == "fiber":
                print(_get_nested_val(products, product, call), "grams of", call, "in", product.capitalize())
            elif call == "calories":
                print(_get_nested_val(products, product, call), "calories in", product.capitalize())

我在想是否可以使用 _get_nested_val() 函数来排序和输出根据用户输入指定的一些产品。

我在 Stack Overflow 上检查了很多其他问题,但未能让我的程序按我想要的方式工作。

python cs50
1个回答
0
投票

如果您不想使用额外的库,则可以执行以下操作:

def top_k_products(nutrient: str, k: int):
    lower_is_better = {"protein": False, "fat": True, "carbs": False, "fiber": False, "calories": True}
    sort_key = lambda item: products[item][nutrient] * (1 if lower_is_better[nutrient] else -1)
    return sorted(products.keys(), key=sort_key)[:k]

这是一个使用示例:

products = {
    "banana": {"protein": 1.3, "fat": 0.4, "carbs": 27.0, "fiber": 3.1, "calories": 105},
    "apple": {"protein": 0.3, "fat": 0.2, "carbs": 13.8, "fiber": 2.4, "calories": 52},
    "orange": {"protein": 0.9, "fat": 0.1, "carbs": 11.8, "fiber": 2.4, "calories": 47},
    "strawberry": {"protein": 0.7, "fat": 0.3, "carbs": 7.7, "fiber": 2.0, "calories": 32},
    "mango": {"protein": 0.8, "fat": 0.4, "carbs": 15.0, "fiber": 1.6, "calories": 60},
    "pineapple": {"protein": 0.5, "fat": 0.1, "carbs": 13.1, "fiber": 1.4, "calories": 50}
}

def top_k_products(nutrient: str, k: int):
    lower_is_better = {"protein": False, "fat": True, "carbs": False, "fiber": False, "calories": True}
    sort_key = lambda item: products[item][nutrient] * (1 if lower_is_better[nutrient] else -1)
    return sorted(products.keys(), key=sort_key)[:k]

print(top_k_products("fat", k=2))
# >>> ['orange', 'pineapple']
print(top_k_products("protein", k=3))
# >>> ['banana', 'orange', 'mango']

其工作原理如下:

  • 通过
    lower_is_better
    ,我们为每种常量营养素定义值越高还是越低越好
  • 通过
    sort_key
    ,我们定义排序标准:我们要排序的
    item
    是外部字典的键,标准是
    nutrient
    的值。我们通过将宏营养素的值分别乘以 1 和 -1 来实现升序与降序排序,具体取决于我们在
    lower_is_better
    字典中为其设置的布尔值。
  • 我们按照这个标准对外部字典的键进行排序,并返回顶部
    k
    结果。

总的来说,我同意其中一条评论,即对于类似的用例使用

pandas
将是更好的选择。

© www.soinside.com 2019 - 2024. All rights reserved.