2010-04-07 18 views
17

Questa potrebbe essere una domanda davvero stupida, tuttavia mi sono guardato in giro online, ecc. E non ho visto una risposta solida.Come posso saltare l'elemento corrente e il prossimo in un loop Python?

C'è un modo semplice per fare qualcosa di simile?

lines = open('something.txt', 'r').readlines() 
for line in lines: 
    if line == '!': 
     # force iteration forward twice 
     line.next().next() 
    <etc> 

È facile da fare in C++; basta incrementare l'iteratore un tempo extra. C'è un modo semplice per farlo in Python?

Vorrei solo sottolineare che lo scopo principale di questa domanda non è "leggere file e cose simili" e saltare le cose. Stavo più cercando l'iterazione di stile iteratore C++. Anche il nuovo titolo è un po 'stupido, e non penso davvero che rifletta la natura della mia domanda.

+5

Un po 'OT, ma non avete bisogno la chiamata a 'readlines()' a meno che non si vuole veramente salvare l'intero file in una lista di linee. 'open()' restituisce già un iteratore che dà accesso alle singole linee. –

+0

Non lo sapevo. Grazie – UberJumper

+0

sì, questo è vero a meno che tu non stia usando Python più vecchio di 2.2: P – wescpy

risposta

25

Prova:

lines = iter(open('something.txt', 'r')) 
for val in lines: 
    if val == "!": 
     lines.next() 
     continue 
    <etc> 

si consiglia di prendere StopIteration da qualche parte. Succederà se l'iteratore è finito.

+5

Puoi usare 'next (lines, None)' per sopprimere l'eccezione 'StopIteration'. (Richiede Python 2.6) – interjay

+0

ogni possibilità di iterazione bidirezionale? – UberJumper

+1

Non con iteratori predefiniti. Puoi comunque creare classi di stili iteratore ignorando le funzioni corrette. – ebo

1

Non molto compatto:

skip = False 
for line in open('something.txt'): 
    if skip: 
    skip = False 
    continue 

    if line.strip() == '!': 
    skip = True 
    continue 
+0

la linea non sarà mai uguale a ''!'' A meno che non spogli prima i caratteri di fine riga dalla fine. – tgray

+0

Risolto aggiungendo .strip() – Harriv

0

si potrebbe usare la ricorsione

input = iter(open('something.txt')) 
def myFunc(item): 
    val = iter.next() 
    if(val == '!'): 
     item.next() 
     return myFunc(item) 
    #continue on with looping logic 

Editted messaggio conteneva la seguente, che in realtà non ha risposto alla tua domanda:

Hai provato

[line for line in open('something.txt') if line != '!'] 

per produrre una nuova lista? O ancora meglio

filter(lambda line: line != '!', open('something.txt')) 
+0

Perché non utilizzare un'espressione generatore piuttosto che una lista di comprensione?Sostituisci semplicemente '[' e ']' con '(' e ')' e sarà comunque iterabile, ma non duplicherà la lista - importante se il file è enorme. –

+1

La versione di ricorsione si interromperà su file con più di 1000 righe (dipende dall'implementazione di Python). – ebo

+1

A meno che non si usi il trampolino malvagio: http://aspn.activestate.com/ASPN/Mail/Message/python-tutor/2302231 –

5

Il metodo file.readlines restituisce un elenco di stringhe e iterando su un elenco non consente di modificare l'iterazione nel corpo del ciclo. Tuttavia, se si iter chiamate sulla lista prima quindi si otterrà un iteratore che è possibile modificare nel corpo del ciclo:

lines = open('something.txt', 'r').readlines() 
line_iter = iter(lines) 
for line in line_iter: 
    if line == '!': 
     # force iteration forward twice 
     line_iter.next() 
     line_iter.next() 
    <etc> 

Come Ebo sottolinea l'oggetto file stesso agisce come un iteratore, in modo da poter ottenere lo stesso effetto non chiamando readlines e lasciando fuori la chiamata a iter.

9

Questa è breve, divinatorio, e lavora:

with open('something.txt', 'r') as f: # or simply f = open('something.txt', 'r') 
    nobang = (line for line in f if line != '!\n') 
    for line in nobang: 
     #... 

Edit:

Come molti osservato, questa non è ancora la soluzione. Il meglio che posso pensare è una combinazione di ciò che è già in questa pagina:

with open('something.txt', 'r') as f: 
    for line in f: 
     if line == '!\n': 
      next(f,None) # consume next line 
      continue # skip this line 
     # ... 
+0

questa è la sintassi p3k, giusto? – Dingle

+3

Questo non salta la riga successiva. – interjay

+0

@Dingle: No, solo 2.6 o successivo. –

Problemi correlati