2012-02-07 11 views
5

Czytam poprzez plik za pomocą pętli for jak to ...iteracja plików, sprawdzanie linii istnienie

f = open("somefile.txt") 

for line in f: 
    do stuff 

wyjątkiem każdej linii czytałem muszę zająć pozycję z linii przed nim i umieść go w bieżącej linii. Jaki jest najlepszy sposób na zrobienie tego? Czy istnieje sposób na odczytanie następnej linii lub pobranie jakiegoś przedmiotu bez przeczytania?

+0

Czy mogę w jakiś sposób sprawdzić, czy istnieje kolejna linia, zanim spróbuję ją przeczytać? –

+0

Co masz na myśli mówiąc "umieść w aktualnej linii" ??? Chcesz zmodyfikować zapisaną linię na twardym dysku z danymi obecnymi na linii? – eyquem

Odpowiedz

6

Jeśli moje rozumienie jest poprawne, i chcesz pracować na każdej linii kolei stosując jakąś wartość z następnego wiersza moją propozycją byłoby po prostu zapisanie wartości, którą właśnie czytasz, i praca nad ostatnią wartością. Działaj w odwrotnej kolejności - linia last_line to Twoja obecna linia, a linia kolejna.

W kategoriach matematycznych, zamiast linii n i linii n + 1, należy wstawić linię n-1 i linię n. Ten sam efekt.

Plusem tej metody nie jest ładowanie całego pliku na początku.

+0

Chciałbym móc głosować na twoją odpowiedź, ale niestety nie mam jeszcze 15 reputacji. Dziękuję, uznałem to za pomocne. –

+0

@ user1178682 Możesz zaakceptować moją odpowiedź, jeśli problem został rozwiązany: http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work/5235#5235 –

3

Jeśli plik nie jest ogromny, można ją czytać w pamięci i używać go tam:

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 

Edit:

przypadku dużych plików, byłoby najłatwiej po prostu pamiętać poprzednia linia:

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 

Możliwe są przypadki brzegowe w zależności od tego, jak wyglądają dane. Czy twoje linie zawsze pojawiają się w parach, czy w niektórych okolicznościach potrzebujesz tylko informacji z następnej linii.

Na przykład ten kod nie zrobi niczego, jeśli plik ma tylko jeden wiersz.

+0

Problem polega na tym, że pliki są dość duże, chcę wykonać przetwarzanie bez konieczności początkowego przechowywania każdej linii w pamięci. Miałem nadzieję, że będzie jakaś metoda, o której nie wiem. Jest to dobra opcja kopii zapasowej, jeśli wszystko inne zawiedzie. Dzięki za odpowiedź. –

+0

W twoim przykładzie edycji, który jest w zasadzie powtórzeniem mojej odpowiedzi, z wyjątkiem tego, że nie używasz z (co powinieneś) i dla pierwszego wykonania, poprzednia linia i linia będą takie same. –

+0

Mam spróbować, klauzula IOException w moim rzeczywisty kod zamiast z (dla zgodności). Jest to raczej uogólnienie, w którym możemy założyć, że plik istnieje i nie zwróci żadnego błędu. Niemniej wydaje się, że konsensus polega na tym, aby po prostu powrócić do poprzedniej linii. Jeśli to jest najlepszy sposób, użyję tego. –

0

Jeśli plik mieści się w pamięci, można spróbować czegoś takiego:

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

Powyższy kod zasadzie czyta wszystkie linie i wykorzystuje zip stworzyć listę krotek zawierający bieżącą linię i następny jeden.

Edit: Alternatywnie, dla długich plików, można użyć itertools bibliotekę następująco:

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

w tym przypadku:

  • itertools.tee jest używany do utworzenia dwóch indenpendent iteratory (jeden dla prądu line i jeden dla następnej linii), które używają oryginalnego iteratora pliku.
  • itertools.slice służy do uruchamiania następnego iteratora linii w drugim wierszu.
  • itertools.izip służy do łączenia wyników obu iteratorów wiersz po wierszu w krotce.

Edit 2: Jak sugeruje @eyquem, można również otworzyć plik dwukrotnie:

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

Nie trzeba używać ** tee() **. Po prostu zdefiniuj inną procedurę obsługi plików: '' g = open ('somefile.txt') '' i przesuń ją o jedną linię do przodu za pomocą '' g.readline() ''. Następnie '' lines = ((f.readline(), linia) dla linii wg) '' – eyquem

+0

@eyquem Dzięki za komentarz. Zmieniłem odpowiedź, aby dołączyć Twój komentarz. – 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