如何将文本文件转换为嵌套字典

问题描述 投票:0回答:3

我是 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()

提前致谢!

python dictionary nested
3个回答
0
投票

以下代码将帮助您生成嵌套字典。您可以根据您的规格更改代码。

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}

0
投票

这并没有回答您关于返回嵌套字典的问题,但是根据您对数据的处理方式,将数据作为一系列数据类可能更容易。

此外,根据您对价值的处理方式,将钱存储为浮动可能会出现问题。更多详细信息,请访问: 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

0
投票
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)
© www.soinside.com 2019 - 2024. All rights reserved.