Reputation: 41
hello i am a beginner of python, there is a simple question. i'm asked to write a generator to traverse a txt file, each row in the file is 3 coordinates of a point (x,y,z) how to return 5 points(5 lines) each time next() is called?
here is my code, i can only generate one line each time thx a lot!
import itertools
def gen_points(name):
f=open(name)
for l in f:
clean_string=l.rstrip()
x,y,z=clean_string.split()
x= float(x)
y= float(y)
z= float(z)
yield x,y,z
f.close()
file_name=r"D:\master ppt\Spatial Analysis\data\22.txt"
a=gen_points(file_name)
g=itertools.cycle(a)
print(next(g))
Upvotes: 4
Views: 148
Reputation: 1525
You don't have to yield immediately, so hold onto the output and then yield it later:
## Adding batchsize so you can change it on the fly if you need to
def gen_points(name, batchsize = 5):
## The "with" statement is better practice
with open(name,'r') as f:
## A container to hold the output
output = list()
for l in f:
clean_string=l.rstrip()
x,y,z=clean_string.split()
x= float(x)
y= float(y)
z= float(z)
## Store instead of yielding
output.append([x,y,z])
## Check if we have enough lines
if len(output) >= batchsize:
yield output
## Clear list for next batch
output = list()
## In case you have an "odd" number of points (i.e.- 23 points in this situation)
if output: yield output
Upvotes: 1
Reputation: 140276
just wait until you have five items in your list of triplets, and yield that instead:
def gen_points(name):
with open(name) as f:
five_items = []
for l in f:
five_items.append(tuple(map(float,l.split())))
if len(five_items) == 5:
yield five_items
# create another empty object
five_items = []
if five_items:
yield five_items
also yield
at the end of the loop if not empty to avoid losing the last elements if the number of elements isn't dividable by 5.
Aside: clean_string=l.rstrip()
was useless since split
already takes care of linefeeds and whatnot.
Upvotes: 5