Python:从一个文件中读取多行,并使实例存储在字典中

Python: Read multiple lines from a file and make instances stored in an dictionary

我的奋斗:

阅读两行并跳过第三行。

然后我想将所有对象存储在字典中,名称作为键。

**** Ingredients.txt ****
Name1
ingredient1/ingredient2/ingredient3

Name2
ingredient1/ingredient2

Name3
...

class Foodset(object):
    def __init__(self, name):
        self.name = name
        self.ingredients = set([])

    def __str__(self):
        return str(self.name) + ' consits of: ' + ", ".join(str(e) for e in self.ingredients) + '.'

    def setIngredients(self, list):
        for i in list:
            self.ingredients.add(i)

def getMenu(file="ingredients.txt"):
    with open(file, 'r') as indata:
        menu = dict()
        for line in indata:
            tempString = str(line.rstrip('\n'))
            menu[tempString] = Foodset(tempString)

我想阅读下一行并将其存储为配料,然后跳过第三行,因为它是空白的。然后重复。

我在 for 循环中遇到的问题是我不能在同一个循环中存储两个不同的行,然后引用同一个对象以使用 setIngredients() 方法。 还有哪些其他方法可以在每个循环中读取多行?

编辑: @Arpan 想出了一个快速解决方案,使用 indata.readlines() 列出每行并以 3 步循环,同时存储第一个和第二个值并跳过第三个值。

我刚刚想出了另一个解决方案,在 while 循环中使用 readline() 方法 3 次。使用 readline() 是我最初想要的。

def getMenu(menu="ingredients.txt"):
    with open(menu, "r") as indata:
        menu = dict()
        while True:
            name = indata.readline().strip('\n')
            ingredientList = indata.readline().strip().split('/')
            if name == "":
                break
# here I just added a parameter that directly set the attribute "ingredients" inside the object.
            menu[name] = Foodset(name, ingredientList)
            indata.readline()
    return menu
    

由于这不是代码编写服务,我将向您展示一种解析文件的方法。根据菜肴及其配料建立字典是简单的部分,所以我会把它留给你。

演示文件input.txt:

Name1
ingredient1/ingredient2/ingredient3

Name2
ingredient1/ingredient2

Name3
ingredient1/ingredient2/ingredient3

代码:

from itertools import izip_longest

with open('input.txt') as infile:
    for name, ingr, _ in izip_longest(*[infile]*3, fillvalue='\n'):
        ingredients = ingr.split('/')
        print name.strip()
        for ing in ingredients:
            print ing.strip()
        print

输出:

Name1
ingredient1
ingredient2
ingredient3

Name2
ingredient1
ingredient2

Name3
ingredient1
ingredient2
ingredient3

解释:

infile是一个迭代器,传了3次给izip_longest,所以每次迭代izip_longest都会对同一个迭代器调用3次next。我使用空行作为 fillvalue 参数,以防您的文件不以空行结尾。

'/' 字符拆分包含配料的字符串将为您提供配料列表。

还有更多 explanation/information 以及一些关于如何一次从文件中读取多行的替代方法 here

尝试这样的事情。

with open(file, 'r') as indata:
    lines = indata.readlines()
menu = dict()
for i in xrange(0, len(lines), 3):
    name = lines[i].rstrip('\n')
    ingredients = lines[i+1].rstrip('\n').split('/')
    f = Foodset(name)
    f.setIngredients(ingredients)
    menu[name] = f

对于 python 3.x 使用 range 而不是 xrange

您可以使用 itertools.islice

一次阅读三行
import itertools
with open('ingredients.txt') as f:
    while True:
        next_three_lines = list(itertools.islice(f, 3))
        if not next_three_lines:
            break
        else:
            print next_three_lines

在你的情况下,这将打印

['Name1\n', 'ingredient1/ingredient2/ingredient3\n', '\n']
['Name2\n', 'ingredient1/ingredient2\n', '\n']
['Name3\n', '...']

然后您可以将打印行更改为 rstrip('\n') 并使用每个 next_three_lines 的前两个元素来构建您的对象:

tempString = str(next_three_lines[0].rstrip('\n'))
menu[tempString] = Foodset(tempString)
menu[tempString].setIngredients(next_three_lines[1].rstrip('\n').split('/')