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}