I am opening a cook-book 'recipes.txt' and it reads like this:
f = open('recipes.txt', 'r', encoding='utf-8')
for x in f:
print(x)
result:
Omelet
3
Egg | 2 | PCS
Milk | 100 | ml
Tomato | 2 | PCS
Peking Duck
4
Duck | 1 | PCS
Water | 2 | l
Honey | 3 | t.sp
Soy sauce | 60 | ml
I need to read / convert it into a nested dictionary format, like this:
cook_book = {
'Omelet': [
{'ingredient_name': 'Egg', 'quantity': 2, 'measure': 'PCS'},
{'ingredient_name': 'Milk', 'quantity': 100, 'measure': 'ml'},
{'ingredient_name': 'Tomato', 'quantity': 2, 'measure': 'PCS'}
],
'Peking Duck': [
{'ingredient_name': 'Duck', 'quantity': 1, 'measure': 'PCS'},
{'ingredient_name': 'Water', 'quantity': 2, 'measure': 'l'},
{'ingredient_name': 'Honey', 'quantity': 3, 'measure': 't.sp'},
{'ingredient_name': 'Soy sauce', 'quantity': 60, 'measure': 'ml'}
]
}
I cannot get on my own how to get exactly desired format. Would appreciate any suggestions.
CodePudding user response:
Hey maybe a little shorter then @Hunters solution
with open('recipes.txt', 'r', encoding='utf-8') as recipes:
cook_book = {}
for line in recipes:
if (line.replace("\n", "")).isnumeric() or line == "\n": # Ignore unwanted lines
continue
elif "|" not in line: # Initialize individual recipes
current_recipe = line.replace("\n", "")
cook_book[current_recipe] = []
elif len(line.strip("|")) > 2: # Add ingredients
ingredient = {}
ingredient_lst = line.split("|")
ingredient["ingredient_name"] = ingredient_lst[0].strip()
ingredient["quantity"] = ingredient_lst[1].strip()
ingredient["measure"] = ingredient_lst[2].replace("\n", "").strip()
cook_book[current_recipe].append(ingredient)
print(cook_book)
If u load any file and read from it you should always use a with block - python will then handle closing the file etc on its own.
EDIT:
If you want to dump the cook_book to a json file you could add this
import json
with open('cook_book.json', 'w', encoding='utf-8') as f:
json.dump(cook_book, f, ensure_ascii=False, indent=4)
Results in this:
{
"Omelet": [
{
"ingredient_name": "Egg ",
"quantity": " 2 ",
"measure": " PCS"
},
{
"ingredient_name": "Milk ",
"quantity": " 100 ",
"measure": " ml"
},
{
"ingredient_name": "Tomato ",
"quantity": " 2 ",
"measure": " PCS"
}
],
"Peking Duck": [
{
"ingredient_name": "Duck ",
"quantity": " 1 ",
"measure": " PCS"
},
{
"ingredient_name": "Water ",
"quantity": " 2 ",
"measure": " l"
},
{
"ingredient_name": "Honey ",
"quantity": " 3 ",
"measure": " t.sp"
},
{
"ingredient_name": "Soy sauce ",
"quantity": " 60 ",
"measure": " ml"
}
]
}
CodePudding user response:
What you have done is just read from the file, whereas you should be taking values from it and assigning it within the dictionaries.
cook_book = {}
indexes = []
with open('recipes.txt', 'r', encoding='utf-8') as fp:
data = fp.read()
linedData = data.split('\n')
i = 0
for line in data.split('\n'):
try:
amount = int(line)
indexes.append(i)
indexes.append(amount)
except:
pass
i = 1
for x in range(len(indexes)):
if (x % 2) == 0:
mealName = linedData[indexes[x]-1]
focusedData = linedData[indexes[x] 1:]
focusedData = focusedData[:(indexes[x 1])]
totalIngredients = []
for line in focusedData:
ingredients = {}
try:
name, amm, ref = line.split(' | ')
ingredients['ingredient_name'] = name
ingredients['quantity'] = int(amm)
ingredients['measure'] = ref
except:
pass
totalIngredients.append(ingredients)
cook_book[mealName] = totalIngredients
print(cook_book)
creates an output of:
{'Omelette': [{'ingredient_name': 'Egg', 'quantity': 2, 'measure': 'PCS'}, {'ingredient_name': 'Milk', 'quantity': 100, 'measure': 'ml'}, {'ingredient_name': 'Tomato', 'quantity': 2, 'measure': 'PCS'}], 'Peking duck': [{'ingredient_name': 'Duck', 'quantity': 1, 'measure': 'PCS'}, {'ingredient_name': 'Water', 'quantity': 2, 'measure': 'l'}, {'ingredient_name': 'Honey', 'quantity': 3, 'measure': 'tbsp'}, {'ingredient_name': 'Soy sauce', 'quantity': 60, 'measure': 'ml'}], 'Baked potatoes': [{'ingredient_name': 'Potatoes', 'quantity': 1, 'measure': 'kg'}, {'ingredient_name': 'Garlic', 'quantity': 3, 'measure': 'tooth'}, {'ingredient_name': 'Gouda cheese', 'quantity': 100, 'measure': 'G'}], 'Fajitos': [{'ingredient_name': 'Beef', 'quantity': 500, 'measure': 'G'}, {'ingredient_name': 'Sweet pepper', 'quantity': 1, 'measure': 'PCS'}, {'ingredient_name': 'Lavash', 'quantity': 2, 'measure': 'state'}, {'ingredient_name': 'Wine vinegar', 'quantity': 1, 'measure': 'tbsp'}, {'ingredient_name': 'Tomato', 'quantity': 2, 'measure': 'state'}]}
But when formatted it creates your desired output of:
{
'Omelette': [
{'ingredient_name': 'Egg', 'quantity': 2, 'measure': 'PCS'},
{'ingredient_name': 'Milk', 'quantity': 100, 'measure': 'ml'},
{'ingredient_name': 'Tomato', 'quantity': 2, 'measure': 'PCS'}
],
'Peking duck': [
{'ingredient_name': 'Duck', 'quantity': 1, 'measure': 'PCS'},
{'ingredient_name': 'Water', 'quantity': 2, 'measure': 'l'},
{'ingredient_name': 'Honey', 'quantity': 3, 'measure': 'tbsp'},
{'ingredient_name': 'Soy sauce', 'quantity': 60, 'measure': 'ml'}
],
'Baked potatoes': [
{'ingredient_name': 'Potatoes', 'quantity': 1, 'measure': 'kg'},
{'ingredient_name': 'Garlic', 'quantity': 3, 'measure': 'tooth'},
{'ingredient_name': 'Gouda cheese', 'quantity': 100, 'measure': 'G'}
],
'Fajitos': [
{'ingredient_name': 'Beef', 'quantity': 500, 'measure': 'G'},
{'ingredient_name': 'Sweet pepper', 'quantity': 1, 'measure': 'PCS'},
{'ingredient_name': 'Lavash', 'quantity': 2, 'measure': 'state'},
{'ingredient_name': 'Wine vinegar', 'quantity': 1, 'measure': 'tbsp'},
{'ingredient_name': 'Tomato', 'quantity': 2, 'measure': 'state'}
]
}
Please bear in mind there are probably more efficient ways of achieving the desired output, and there will be ways to refactor my code, but this is my attempt at the question.
Hope this helps.