Python:从文件中读取多行并将实例存储在字典中
Posted
技术标签:
【中文标题】Python:从文件中读取多行并将实例存储在字典中【英文标题】:Python: Read multiple lines from a file and make instances stored in an dictionary 【发布时间】:2016-07-26 15:32:33 【问题描述】:我的奋斗:
阅读两行并跳过第三行。
然后我想将所有对象存储在字典中,名称为键。
**** 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
【问题讨论】:
这是多个问题合而为一的问题。你能隔离问题吗?是读取文件的问题,一次得到三行问题吗?构建您的自定义对象是问题吗?如果您编辑问题以仅包含您正在努力解决的部分的最小示例,您将更快地获得帮助。 【参考方案1】:试试这样的。
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
。
【讨论】:
所以列出一个列表并使用索引似乎是一个解决方案。为什么要使用 xrange? (我现在正在尝试) 使用 range 生成一个包含所有对象的列表,而使用 xrange 是一个延迟计算的序列对象。 ***.com/questions/94935/… 好吧,太完美了。非常简单易用。我会精简我的问题,以便其他人更容易理解。我对 Stack Overflow 的第一个问题非常感谢您理解问题并迅速解决它。我是否只需单击“已解决”复选标记,您就明白了吗? 不客气@TheRawPerformer。如果您喜欢答案,您也可以单击upvote 按钮。 :) 很遗憾,我无法投票,因为我还没有任何声望点。是否表明您的回答解决了我的问题?【参考方案2】:您可以使用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('/')
【讨论】:
感谢您的回答。我一定会记住这种方法,因为它看起来非常有用和干净。 +1【参考方案3】:由于这不是代码编写服务,我将向您展示一种解析文件的方法。根据菜肴及其成分构建字典是很简单的部分,所以我将把它留给你。
演示文件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
是一个迭代器,它向izip_longest
传递了3 次,所以每次迭代izip_longest
都会在同一个迭代器上调用next
3 次。我使用空行作为 fillvalue
参数,以防您的文件不以空行结尾。
用'/'
字符分割带有成分的字符串将为您提供成分列表。
关于如何一次从文件中读取多行 here 有更多解释/信息以及一些替代方法。
【讨论】:
以上是关于Python:从文件中读取多行并将实例存储在字典中的主要内容,如果未能解决你的问题,请参考以下文章
将项目的密钥存储在并发字典中,该项目的密钥作为在C#中的字典中出现的次数