Working on my final project for cs50 Introduction to programming with Python. Trying to implement a programm with a few functions, such as: calculating basal metabolic rate, formatting a list of products, printing a nutritional value of a user specified product and suggesting/sorting products by their value depending on a macronutrient specified by user.
Having trouble with the latter function.
I have a two-level deep dict of different products with their nutritional value:
products = {
"almonds": {"protein": 6.0, "fat": 14.2, "carbs": 6.1, "fiber": 3.5, "calories": 164},
"banana": {"protein": 1.3, "fat": 0.4, "carbs": 27.0, "fiber": 3.1, "calories": 105},
"buckwheat": {"protein": 5.7, "fat": 1.0, "carbs": 34.0, "fiber": 4.5, "calories": 155},
"ground beef": {"protein": 24.0, "fat": 13, "carbs": 0, "fiber": 0, "calories": 218}
}
I want to implement a function which asks the user for a macronutrient (protein, fat, carbs, fiber or calories - all are the keys for a nested dict), searches through the products dict and then outputs a top-three products, based on their nutritional value specified by user.
I am having trouble with sorting the dict by it's value (as I see it). Thought about storing the value as a nested list:
products = {"banana": [1.3, 0.4, 27.0, 3.1, 105]}
So I can call a value by:
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
But the products dict seems kind of cryptic anyway, so I would like to avoid this option.
As of now I have the following function:
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:])
I call this function in main() for showing the user a nutritional value of a specific product:
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())
I was wondering if I can use _get_nested_val() function to sort and output a few products, specified by user's input.
def main():
initial = input("What do you want the programm to do? ").lower().strip()
... # other functions are called here, not relevant to the current problem
elif initial == "suggest":
suggest()
def suggest():
req = input("Based on what macronutrient would you like the products to be suggested? ")
if request == "protein":
...
### I would like to see the programm running like something this:
# $ What do you want the programm to do? suggest
# $ Based on what macronutrient would you like the products to be suggested? protein
# The following products are high in protein: Beef, Chicken breast, ...
I have checked a lot of other questions on Stack Overflow but fail to get my programm to work as I want it to.
Your starting point should be to develop a class that supports the nutritional values. That will make your code more concise and easier to maintain.
The problem you're having (as I understand it) is that you want user input of a macronutrient (e.g., fat, carbs) then sort your products dictionary based on the macronutrient value.
If that's the case then:
from collections import UserDict
class Nutrients(UserDict):
MN = ["protein", "fat", "carbs", "fibre", "calories"]
def __init__(self, *args):
super().__init__()
assert len(args) == len(Nutrients.MN)
self.data.update(zip(Nutrients.MN, args))
products: dict[str, Nutrients] = {
"almonds": Nutrients(6.0, 14.2, 6.1, 3.5, 164),
"banana": Nutrients(1.3, 0.4, 27.0, 3.1, 105),
"buckwheat": Nutrients(5.7, 1.0, 34.0, 4.5, 155),
"ground beef": Nutrients(24.0, 13, 0, 0, 218),
}
mn = input("Input macronutrient: ")
if mn in Nutrients.MN:
print(f"The following are high in {mn}:")
for p, _ in sorted(products.items(), key=lambda t: t[1][mn], reverse=True):
print(f"\t{p.capitalize()}")
Terminal:
Input macronutrient: protein
The following are high in protein:
Ground beef
Almonds
Buckwheat
Banana