Reputation: 7918
Is there a better way to read lines two at a time from a file in python than:
with open(fn) as f:
for line in f:
try:
line2 = f.next()
except StopIteration:
line2 = ''
print line, line2 # or something more interesting
I'm in 2.5.4. Anything different in newer versions?
EDIT: a deleted answer noted: in py3k you'd need to do next(f) instead of f.next(). Not to mention the print change
Upvotes: 14
Views: 4205
Reputation: 882291
import itertools
with open(fn) as f:
for line, line2 in itertools.izip_longest(f, f, fillvalue=''):
print line, line2
Alas, izip_longest
requires Python 2.6 or better; 2.5 only has izip
, which would truncate the last line if f
has an odd number of lines. It's quite easy to supply the equivalent functionality as a generator, of course.
Here's a more general "N at a time" iterator-wrapper:
def natatime(itr, fillvalue=None, n=2):
return itertools.izip_longest(*(iter(itr),)*n, fillvalue=fillvalue)
itertools
is generally the best way to go, but, if you insisted on implementing it by yourself, then:
def natatime_no_itertools(itr, fillvalue=None, n=2):
x = iter(itr)
for item in x:
yield (item,) + tuple(next(x, fillvalue) for _ in xrange(n-1))
In 2.5, I think the best approach is actually not a generator, but another itertools-based solution:
def natatime_25(itr, fillvalue=None, n=2):
x = itertools.chain(iter(itr), (fillvalue,) * (n-1))
return itertools.izip(*(x,)*n)
(since 2.5 doesn't have the built-in next
, as well as missing izip_longest
).
Upvotes: 18
Reputation: 2990
You could possibly make it more clear with a generator:
def read2(f):
for line in f:
try:
line2 = f.next()
except StopIteration:
line2 = ''
yield line, line2
with open(fn) as f:
for line1, line2 in read2(f):
print line1
print line2
Upvotes: 2
Reputation: 342739
for small to medium sized files,
>>> data=open("file").readlines()
>>> for num,line in enumerate(data[::2]):
... print ''.join(data[num:num+2])
Upvotes: 1