2009-10-06 4 views
12

Y at-il une meilleure façon de lire les lignes deux à la fois d'un fichier en python que:lignes de lecture 2 à un moment

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

Je suis en 2.5.4. Quelque chose de différent dans les versions plus récentes?

EDIT: une réponse supprimé note: en Py3K vous aurez besoin de faire ensuite (f) au lieu de f.next(). Sans parler du changement d'impression

Répondre

16
import itertools 

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

Hélas, izip_longest nécessite Python 2.6 ou mieux; 2.5 a seulement izip, qui tronquerait la dernière ligne si f a un nombre impair de lignes. Il est assez facile de fournir la fonctionnalité équivalente en tant que générateur, bien sûr.

est ici un « N à la fois » plus générale iterator-emballage:

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

itertools est généralement la meilleure façon d'aller, mais si vous insistez sur la mise en œuvre par vous-même, puis:

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

En 2.5, je pense que la meilleure approche est en fait pas un générateur, mais une autre solution itertools-:

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

(depuis 2.5 n'a pas intégré dans next, ainsi que manque izip_longest).

+0

+1: suggestion pour générateur Py2.5 –

+0

n'a jamais prêté attention à le paramètre 'default' de' next', merci de le signaler. – SilentGhost

+0

essayez/sauf semble simple et clair (et ne serait pas nécessaire si nous pouvions garantir un nombre pair de lignes). Pourquoi préféreriez-vous écrire un générateur ici? Le générateur n'exigerait-il pas un essai/excepté? – foosion

1

pour les petites et fichiers de taille moyenne,

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

Vous pourriez le rendre plus clair avec un générateur:

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 
Questions connexes