2012-02-07 16 views
5

estoy leyendo a través de un archivo utilizando un bucle como este ...iteración del archivo, comprobación de la existencia de línea

f = open("somefile.txt") 

for line in f: 
    do stuff 

excepto por cada línea leí i necesidad de tomar un elemento de la línea por delante de ella y ponerlo en la línea actual. ¿Cuál es la mejor manera de hacer esto? ¿Hay alguna forma de leer la siguiente línea u obtener algún elemento sin leerla?

+0

¿O puedo de alguna manera verificar si la siguiente línea existe antes de intentar leerla? –

+0

¿Qué quiere decir con 'ponerlo en la línea actual'? ¿Desea modificar una línea grabada en el disco duro con los datos presentes en la línea de delante? – eyquem

Respuesta

6

Si mi interpretación es correcta, y que desea trabajar en cada línea, a su vez, el uso de un cierto valor de la línea siguiente, mi sugerencia sería simplemente almacenar el valor que está leyendo actualmente, y trabajar en el último valor. Trabaja en reversa: el last_line es tu línea actual y la línea es la siguiente.

last_line = None 

with open("somefile.txt") as f: 
    for line in f: 
     if not last_line == None: 
      do_stuff(last_line, extract_needed_part(line)) 
     last_line = line 
do_stuff(last_line) #The final line without anything following it. 

En términos matemáticos, en lugar de la línea n y la línea n + 1, hacer la línea n-1 y la línea n. Mismo efecto.

Lo bueno de este método es que no significa cargar todo el archivo al principio.

+0

Desearía poder votar su respuesta, pero desafortunadamente aún no tengo 15 de reputación. Gracias, sin embargo, encontré esto útil. –

+0

@ user1178682 Puede aceptar mi respuesta, si ha resuelto su problema: http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work/5235#5235 –

3

Si el archivo no es muy grande, se puede leer en la memoria y utiliza allí:

f = open("somefile.txt") 
lines = f.readlines() 
f.close() 

for index, value in enumerate(lines): 
    # Check if next line exists 
    if index + 1 > len(lines): 
     next_line = lines(index + 1) 
     # do something with line and next_line 

Editar:

Para archivos de gran tamaño, que sería más fácil de simplemente recordar su anterior línea:

f = open("somefile.txt") 
previous_line = f.readline() 
for line in f: 
    # Do something with line and previous_line 
    print(line, previous_line) 
    # Save this line for the next iteration 
    previous_line = line 

Puede haber casos extremos dependiendo de cómo sean sus datos. ¿Sus líneas siempre vienen en pares o solo necesita un poco de información de la siguiente línea en ciertas circunstancias?

Por ejemplo, este código no hará nada si su archivo solo tiene una línea.

+0

El problema es que los archivos son bastante grandes, quiero hacer el procesamiento sin tener que almacenar cada línea en la memoria inicialmente. Esperaba que hubiera algún método que desconozco. Esta es una buena opción de copia de seguridad si todo lo demás falla. Gracias por responder. –

+0

En su ejemplo para su edición, que es más o menos una repetición de mi respuesta, excepto que no está utilizando con (lo que debería) y para la primera ejecución, la línea anterior y la línea serán las mismas. –

+0

Tengo una cláusula try, IOException en mi código actual en lugar de a con (por compatibilidad). Esto es más una generalización, donde podemos suponer que el archivo existe y no devolverá ningún error. No obstante, el consenso parece ser simplemente aferrarse a la línea anterior. Si es la mejor manera, lo usaré. –

0

Si el archivo se ajusta en la memoria, se puede intentar algo como esto:

f = open('somefile.txt') 
lines = f.read().splitlines() 

for current_line, next_line in zip(lines, lines[1:]): 
    print current_line 
    print next_line 
    print '-------' 

El código anterior, básicamente, lee todas las líneas y utiliza zip para crear una lista de tuplas que contiene la línea actual y el siguiente uno.

Editar: Como alternativa, para archivos largos, puede utilizar itertools biblioteca de la siguiente manera:

import itertools 
f = open('somefile.txt') 
i1, i2 = itertools.tee(f) 
lines = itertools.izip(i1, itertools.islice(i2, 1, None)) 
for current_line, next_line in lines: 
    print current_line 
    print next_line 
    print '-------' 

En este caso:

  • itertools.tee se utiliza para crear dos iteradores indenpendent (uno para la corriente línea y uno para la línea siguiente) que utilizan el iterador de archivo original.
  • itertools.slice se utiliza para iniciar el siguiente iterador de línea en la segunda línea.
  • itertools.izip se utiliza para unir los resultados de ambos iteradores línea por línea en una tupla.

Edición 2: Como sugiere @eyquem, también puede abrir el archivo dos veces:

import itertools 
f = open('somefile.txt') 
g = open('somefile.txt') 
lines = itertools.izip(f, itertools.islice(g, 1, None)) 
for current_line, next_line in lines: 
    print current_line 
    print next_line 
    print '-------' 
+1

No es necesario utilizar ** tee() **. Simplemente defina otro manejador de archivos: '' g = open ('somefile.txt') '' y haga que se mueva una línea adelante con '' g.readline() ''. Luego '' lines = ((f.readline(), línea) para la línea en g) '' – eyquem

+0

@eyquem Gracias por su comentario. He editado la respuesta para incluir tu comentario. – jcollado

0
with open('somefile.txt') as f, open('somefile.txt') as g: 
    g.readline() 
    lines = ((f.readline(),line) for line in g) 
     for precline,aheadline in lines: 
      # do what you want 
Cuestiones relacionadas