2009-10-06 34 views
12

Có cách nào tốt hơn để đọc các dòng hai cùng một lúc từ một tập tin trong python hơn:đọc dòng 2 tại một thời điểm

with open(fn) as f: 
    for line in f: 
     try: 
      line2 = f.next() 
     except StopIteration: 
      line2 = '' 
     print line, line2 # or something more interesting 

Tôi đang ở 2.5.4. Bất cứ điều gì khác nhau trong các phiên bản mới hơn?

EDIT: câu trả lời đã xóa ghi chú: trong py3k bạn cần thực hiện (f) tiếp theo thay vì f.next(). Chưa kể đến thay đổi in

Trả lời

16
import itertools 

with open(fn) as f: 
    for line, line2 in itertools.izip_longest(f, f, fillvalue=''): 
    print line, line2 

Alas, izip_longest yêu cầu Python 2.6 trở lên; 2.5 chỉ có izip, sẽ cắt ngắn dòng cuối cùng nếu f có số dòng lẻ. Nó khá dễ dàng để cung cấp các chức năng tương đương như một máy phát điện, tất nhiên.

Dưới đây là một "N tại một thời điểm" tổng quát hơn iterator-wrapper:

def natatime(itr, fillvalue=None, n=2): 
    return itertools.izip_longest(*(iter(itr),)*n, fillvalue=fillvalue) 

itertools thường là cách tốt nhất để đi, nhưng, nếu bạn khăng khăng đòi thực hiện nó bằng chính mình, sau đó:

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)) 

Trong 2.5, tôi nghĩ rằng cách tiếp cận tốt nhất là thực sự không phải là một máy phát điện, nhưng một giải pháp itertools dựa trên:

def natatime_25(itr, fillvalue=None, n=2): 
    x = itertools.chain(iter(itr), (fillvalue,) * (n-1)) 
    return itertools.izip(*(x,)*n) 

(kể từ 2.5 không có sẵn next, cũng như thiếu izip_longest).

+0

+1: gợi ý cho máy phát điện trong Py2.5 –

+0

không bao giờ chú ý đến tham số 'default' của' next', cảm ơn bạn đã chỉ ra điều đó. – SilentGhost

+0

thử/ngoại trừ có vẻ đơn giản và rõ ràng (và sẽ không cần thiết nếu chúng tôi có thể đảm bảo một số dòng đồng đều). tại sao bạn thích viết một máy phát điện ở đây? Máy phát điện sẽ không cần thử/ngoại trừ? – foosion

1

cho nhỏ đến các tập tin có kích thước trung bình,

>>> data=open("file").readlines() 
>>> for num,line in enumerate(data[::2]): 
... print ''.join(data[num:num+2]) 
2

Bạn có thể có thể làm cho nó rõ ràng hơn với một máy phát điện:

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 
Các vấn đề liên quan