I wanted to build a simple python script that could add all the items from multiple recipes into an excel document to make shopping and sticking to a meal plan easier. I was able to get a simple version working, however when it exports to excel if multiple recipes have the same ingredient it will have it in the excel document multiple times. I have been trying to instead have it add the quantity of that ingredient together instead of repeating it. Below is a sample of two recipe ingredients.
import pandas as pd
friedRiceShrimp = [
{"Ingredient": "Garlic clove", "Size": "clove", "Quantity": 3, "Aisle": "Produce"},
{"Ingredient": "Instant Brown Rice", "Size": "oz", "Quantity": 16, "Aisle": 22},
{"Ingredient": "Soy Sauce", "Size": "tbsp", "Quantity": 2, "Aisle": 22},
{"Ingredient": "Chili Paste", "Size": "tbsp", "Quantity": 2, "Aisle": 22},
{"Ingredient": "Honey", "Size": "tbsp", "Quantity": 1, "Aisle": 18},
{"Ingredient": "Peanut Oil", "Size": "tbsp", "Quantity": 2, "Aisle": 21},
{"Ingredient": "Shrimp", "Size": "oz", "Quantity": 10, "Aisle": 12},
{"Ingredient": "Egg", "Size": "individual", "Quantity": 3, "Aisle": "Dairy"},
{"Ingredient": "Snap Peas", "Size": "cup", "Quantity": 1.5, "Aisle": "Produce"},
{"Ingredient": "Peanuts Dry-Roasted", "Size": "cup", "Quantity": .3, "Aisle": 14}
]
macNCheese = [
{"Ingredient": "Bacon", "Size": "Slice", "Quantity": 6, "Aisle": 8},
{"Ingredient": "Chicken Stock", "Size": "cup", "Quantity": 2, "Aisle": 24},
{"Ingredient": "Milk", "Size": "cup", "Quantity": 1, "Aisle": "Dairy"},
{"Ingredient": "Butternut Squash puree", "Size": "oz", "Quantity": 10, "Aisle": "Produce"},
{"Ingredient": "Macaroni Elbow Pasta", "Size": "oz", "Quantity": 10, "Aisle": 23},
{"Ingredient": "Broccoli", "Size": "cup", "Quantity": 3, "Aisle": "Produce"},
{"Ingredient": "Cheddar Cheese Shredded", "Size": "oz", "Quantity": 5, "Aisle": 8},
{"Ingredient": "Garlic clove", "Size": "clove", "Quantity": 2, "Aisle": "Produce"}
]`
shopping_list = friedRiceShrimp macNCheese
df = pd.DataFrame(data=shopping_list)
df.to_excel("Test.xlsx", index=False)
I tried the below and several different loops. My idea is to loop through shopping_list and with each item add it to a new list. If the item is already in the new list (and "Size" is the same) the quantity will be added together instead of having a duplicate item show up in my excel export. The issue I have is I matching just the Ingredient in idx compared to everything in final_list. I also am willing and understand that I may need to rework this from the ground up to make my final vision work.
shopping_list = friedRiceShrimp macNCheese
final_list = []
for idx in shopping_list:
if idx["Ingredient"] in final_list[0]["Ingredient"]: #needs to check if idx ingredent is already in list somehow
final_list[0]["Quantity"] = idx["Quantity"] #if that idx ingredent in final list add just quantity
else:
final_list.append(idx)
print(idx["Ingredient"])
Thank you for the help and assistance, still learning python and trying to find ways to use it in my everyday life a bit more to help cement ideas and concepts.
CodePudding user response:
Essentially, you are trying to merge/roll up duplicated records with same ('Ingredient', 'Size') attributes and sum up their Quantity.
Use pandas power to group by the needed columns and aggregate by other columns that need to be calculated or reduced.
shopping_list = friedRiceShrimp macNCheese
df = pd.DataFrame(data=shopping_list)
df = df.groupby(['Ingredient', 'Size'], as_index=False).agg({'Quantity': 'sum', 'Aisle': 'first'})
print(df)
Ingredient Size Quantity Aisle
0 Bacon Slice 6.0 8
1 Broccoli cup 3.0 Produce
2 Butternut Squash puree oz 10.0 Produce
3 Cheddar Cheese Shredded oz 5.0 8
4 Chicken Stock cup 2.0 24
5 Chili Paste tbsp 2.0 22
6 Egg individual 3.0 Dairy
7 Garlic clove clove 5.0 Produce
8 Honey tbsp 1.0 18
9 Instant Brown Rice oz 16.0 22
10 Macaroni Elbow Pasta oz 10.0 23
11 Milk cup 1.0 Dairy
12 Peanut Oil tbsp 2.0 21
13 Peanuts Dry-Roasted cup 0.3 14
14 Shrimp oz 10.0 12
15 Snap Peas cup 1.5 Produce
16 Soy Sauce tbsp 2.0 22
CodePudding user response:
You could do it like this in Python
shopping_list = friedRiceShrimp macNCheese
final_list = []
for ingredient_to_add in shopping_list:
# returns the first dictionary that satisfies the condition for Ingredient name and size
# returns None if there is no dictionary in final_list that satisfies the condition
match = next((ingredient for ingredient in final_list if
ingredient['Ingredient'] == ingredient_to_add['Ingredient'] and ingredient['Size'] ==
ingredient_to_add['Size']), None)
# if the ingredient already exists in final_list we add to the quantity of the existing element that of the new ingredient
if match:
match['Quantity'] = ingredient_to_add['Quantity']
# otherwise we simply add the ingredient
else:
final_list.append(ingredient_to_add)
for ingredient in final_list:
print(ingredient)
Output
{'Ingredient': 'Garlic clove', 'Size': 'clove', 'Quantity': 5, 'Aisle': 'Produce'}
{'Ingredient': 'Instant Brown Rice', 'Size': 'oz', 'Quantity': 16, 'Aisle': 22}
{'Ingredient': 'Soy Sauce', 'Size': 'tbsp', 'Quantity': 2, 'Aisle': 22}
{'Ingredient': 'Chili Paste', 'Size': 'tbsp', 'Quantity': 2, 'Aisle': 22}
{'Ingredient': 'Honey', 'Size': 'tbsp', 'Quantity': 1, 'Aisle': 18}
{'Ingredient': 'Peanut Oil', 'Size': 'tbsp', 'Quantity': 2, 'Aisle': 21}
{'Ingredient': 'Shrimp', 'Size': 'oz', 'Quantity': 10, 'Aisle': 12}
{'Ingredient': 'Egg', 'Size': 'individual', 'Quantity': 3, 'Aisle': 'Dairy'}
{'Ingredient': 'Snap Peas', 'Size': 'cup', 'Quantity': 1.5, 'Aisle': 'Produce'}
{'Ingredient': 'Peanuts Dry-Roasted', 'Size': 'cup', 'Quantity': 0.3, 'Aisle': 14}
{'Ingredient': 'Bacon', 'Size': 'Slice', 'Quantity': 6, 'Aisle': 8}
{'Ingredient': 'Chicken Stock', 'Size': 'cup', 'Quantity': 2, 'Aisle': 24}
{'Ingredient': 'Milk', 'Size': 'cup', 'Quantity': 1, 'Aisle': 'Dairy'}
{'Ingredient': 'Butternut Squash puree', 'Size': 'oz', 'Quantity': 10, 'Aisle': 'Produce'}
{'Ingredient': 'Macaroni Elbow Pasta', 'Size': 'oz', 'Quantity': 10, 'Aisle': 23}
{'Ingredient': 'Broccoli', 'Size': 'cup', 'Quantity': 3, 'Aisle': 'Produce'}
{'Ingredient': 'Cheddar Cheese Shredded', 'Size': 'oz', 'Quantity': 5, 'Aisle': 8}
