我是 Python 的初学者。我需要一些帮助将文本文件转换为嵌套的字典。具有一定的格式。
文本文件如下所示:
espresso, ingredients, water, 50, coffee, 18, cost, 1.5
latte, ingredients, water, 200, milk, 150, coffee, 24, cost, 2.5
cappuccino, ingredients, water, 250, milk, 100, coffee, 4, cost, 3.0
我试图让输出看起来像这样:
MENU = {"espresso": {"ingredients": {"water": 50, "coffee": 18}, "cost": 1.5},
"latte": {"ingredients": {"water": 200, "milk": 150, "coffee": 24}, "cost": 2.5},
"cappuccino": {"ingredients": {"water": 250, "milk": 100, "coffee": 24}, "cost": 3.0}}
这是我目前的代码:
def open_file() -> IO:
"""
Ask the user for the input menu file and open it
"""
file_pointer = None
# prompts the user to enter a file name until a valid file is entered
while file_pointer is None:
# prompts the user to enter a file name
file_name = input("Please enter a menu file: ")
# try to open the file
try:
file_pointer = open(file_name, "r")
# display an error message if cannot open file
except IOError:
print("An error has occurred, please try again. ")
return file_pointer
def create_menu(fp: IO) -> Dict [str, Dict [str, float]]:
"""
Creates a menu based on the inputted file in the form of a nested Dict
"""
MENU = {}
for line in fp:
drink_detail = line.strip().split()
提前致谢!
以下代码将帮助您生成嵌套字典。您可以根据您的规格更改代码。
menu = {}
items = line.split(',')
drink = items[0]
ingredients = {}
for i in range(2, len(items)-2, 2):
ingredient, amount = items[i], items[i+1]
ingredients[ingredient.strip()] = float(amount.strip())
cost = float(items[-1].strip())
menu[drink] = {'ingredients': ingredients, 'cost': cost}
这并没有回答您关于返回嵌套字典的问题,但是根据您对数据的处理方式,将数据作为一系列数据类可能更容易。
此外,根据您对价值的处理方式,将钱存储为浮动可能会出现问题。更多详细信息,请访问: https://smirnov-am.github.io/representing-money-in-python/
从文件中提取数据到数据类的示例
import textwrap
from dataclasses import dataclass, field
from pathlib import Path
from typing import Optional
# Create menu file for testing
data_in = textwrap.dedent(
"""
espresso, ingredients, water, 50, coffee, 18, cost, 1.5
latte, ingredients, water, 200, milk, 150, coffee, 24, cost, 2.5
cappuccino, ingredients, water, 250, milk, 100, coffee, 4, cost, 3.0
"""
)
file_name = "test_menu.txt"
Path(file_name).write_text(data_in, "utf8")
# End creating menu test file
@dataclass
class Ingredient:
product: str
qty: int
@dataclass
class Drink:
name: str
ingredients: list[Ingredient] = field(default_factory=list)
cost: Optional[int] = None
def show_ingredients(self) -> None:
for ingredient in self.ingredients:
print(f"\t{ingredient.product:<10}: {ingredient.qty:>4}")
@dataclass
class Menu:
drinks: list[Drink] = field(default_factory=list)
def get_drink(self, name: str) -> Drink:
for drink in self.drinks:
if drink.name.casefold() == name.casefold():
return drink
def add_drink(self, name: str) -> None:
self.drinks.append(Drink(name))
def add_cost(self, name: str, cost: int) -> None:
drink = self.get_drink(name)
drink.cost = cost
def add_ingredient(self, drink_name: str, name: str, qty: int) -> None:
drink = self.get_drink(drink_name)
drink.ingredients.append(Ingredient(name, qty))
def show_ingredients(self, drink_name: str) -> None:
drink = self.get_drink(drink_name)
print(f"Showing ingredients for {drink.name}")
drink.show_ingredients()
def process_data(menu_data: str) -> Menu:
menu = Menu()
for drink in menu_data:
drink_name = None
for entry in drink:
if entry[1] == "ingredients":
drink_name = entry[0]
menu.add_drink(drink_name)
elif entry[0] == "cost":
drink_price = int(float(entry[1]) * 100)
menu.add_cost(drink_name, drink_price)
else:
menu.add_ingredient(drink_name, entry[0], int(entry[1]))
return menu
def process_file(filepath: Path) -> Menu:
menu_data = []
for line in filepath.read_text('utf8').splitlines():
if line:
fields = line.split(",")
menu_data.append(
[(k.strip(), v.strip()) for k, v in zip(fields[::2], fields[1::2])]
)
return process_data(menu_data)
def main() -> None:
menu = process_file(Path(file_name))
for drink in menu.drinks:
print(drink)
print("\nShow just one drink:")
menu.show_ingredients('latte')
print("\nShow ingredients for all drinks:")
for drink in menu.drinks:
print(f"Showing ingredients for {drink.name}")
drink.show_ingredients()
if __name__ == "__main__":
main()
这个例子给了我以下输出:
Drink(name='espresso', ingredients=[Ingredient(product='water', qty=50), Ingredient(product='coffee', qty=18)], cost=150)
Drink(name='latte', ingredients=[Ingredient(product='water', qty=200), Ingredient(product='milk', qty=150), Ingredient(product='coffee', qty=24)], cost=250)
Drink(name='cappuccino', ingredients=[Ingredient(product='water', qty=250), Ingredient(product='milk', qty=100), Ingredient(product='coffee', qty=4)], cost=300)
Show just one drink:
Showing ingredients for latte
water : 200
milk : 150
coffee : 24
Show ingredients for all drinks:
Showing ingredients for espresso
water : 50
coffee : 18
Showing ingredients for latte
water : 200
milk : 150
coffee : 24
Showing ingredients for cappuccino
water : 250
milk : 100
coffee : 4
menu_dict = {}
with open("yourTextFile.txt", "r") as data:
for row in data:
temp_row = row.split(",")
key = temp_row[0]
if key not in menu_dict.keys():
menu_dict[key] = {"ingredients": {}, "cost": temp_row[-1]}
for i in range(2, len(temp_row) - 2, 2):
menu_dict[key]["ingredients"][temp_row[i]] = temp_row[i + 1]
print(menu_dict)