问题
My struggle:
Reading two lines and jumping over the third.
Then I want to store all the objects in a dictionary with the name as keys.
**** 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)
I want to read the next line and store as ingredients and then skip the third line since it's blank. Then repeat.
The problem I'm having with the for loop is that I can't store two different lines in the same loop and then refer to the same object in order to use the setIngredients() method. What other ways can I read multiple lines inside each loop?
EDIT: @Arpan came up with a quick solution to use indata.readlines() to make a list of every line and loop with steps of 3 while storing first and second value and skipping the third.
I just came up with an other solution using the readline() method 3 times inside a while loop. Using readline() is what I originally wanted.
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:
Try something like this.
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
For python 3.x use range
instead of xrange
.
回答2:
You can read three lines at once using 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
In your case this will print
['Name1\n', 'ingredient1/ingredient2/ingredient3\n', '\n']
['Name2\n', 'ingredient1/ingredient2\n', '\n']
['Name3\n', '...']
Then you can change the print line to rstrip('\n')
and use the first two elements of each next_three_lines
to build your object:
tempString = str(next_three_lines[0].rstrip('\n'))
menu[tempString] = Foodset(tempString)
menu[tempString].setIngredients(next_three_lines[1].rstrip('\n').split('/')
回答3:
Since this is not a code writing service, I will show you a way to parse your file. Building a dictionary from the dishes and their ingredients is the simple part, so I will leave that to you.
Demo file input.txt:
Name1
ingredient1/ingredient2/ingredient3
Name2
ingredient1/ingredient2
Name3
ingredient1/ingredient2/ingredient3
Code:
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
Output:
Name1
ingredient1
ingredient2
ingredient3
Name2
ingredient1
ingredient2
Name3
ingredient1
ingredient2
ingredient3
Explanation:
infile
is an iterator, which is passed three times to izip_longest
, so each iteration izip_longest
will call next
on the same iterator three times. I use an empty line as the fillvalue
argument in case your file does not end with an empty line.
Splitting the string with the ingredients by the '/'
character will give you a list of ingredients.
There's more explanation/information and also some alternatives on how to read multiple lines from a file at once here.
来源:https://stackoverflow.com/questions/36447597/python-read-multiple-lines-from-a-file-and-make-instances-stored-in-an-dictiona