Si sta iterando su un elenco ed eliminando elementi da esso allo stesso tempo.
Prima di tutto, devo assicurarmi di capire chiaramente il ruolo di char
in for char in textlist: ...
. Prendi la situazione in cui abbiamo raggiunto la lettera "l". La situazione è non in questo modo:
['H', 'e', 'y', ' ', 'l', 'o', 'o', 'k', ' ', 'W', 'o', 'r', 'd', 's', '!']
^
char
Non v'è alcun legame tra char
e la posizione della lettera 'L' nella lista.Se modifichi char
, l'elenco non verrà modificato. La situazione è più simile a questo:
['H', 'e', 'y', ' ', 'l', 'o', 'o', 'k', ' ', 'W', 'o', 'r', 'd', 's', '!']
^
char = 'l'
Si noti che ho mantenuto il simbolo ^
. Questo è il puntatore nascosto che il codice che gestisce il ciclo for char in textlist: ...
utilizza per tenere traccia della sua posizione nel ciclo. Ogni volta che si immette il corpo del ciclo, il puntatore viene avanzato e la lettera a cui fa riferimento il puntatore viene copiata in char
.
Il tuo problema si verifica quando hai due vocali in successione. Ti mostrerò cosa succede dal punto in cui raggiungi "l". Si noti che ho anche cambiato la parola "look" per "salto", per renderlo più chiaro quello che sta succedendo:
puntatore anticipo per carattere successivo ('l') e copiare char
['H', 'e', 'y', ' ', 'l', 'e', 'a', 'p', ' ', 'W', 'o', 'r', 'd', 's', '!']
->^
char = 'l'
char
('l') non è una vocale, in modo da non fare nulla
puntatore anticipo per carattere successivo ('e') e copiare char
['H', 'e', 'y', ' ', 'l', 'e', 'a', 'p', ' ', 'W', 'o', 'r', 'd', 's', '!']
->^
char = 'e'
char
('e') è una vocale, in modo da eliminare la prima occorrenza di char
('e') puntatore
['H', 'e', 'y', ' ', 'l', 'e', 'a', 'p', ' ', 'W', 'o', 'r', 'd', 's', '!']
^
['H', 'e', 'y', ' ', 'l', 'a', 'p', ' ', 'W', 'o', 'r', 'd', 's', '!']
^
['H', 'e', 'y', ' ', 'l', <- 'a', 'p', ' ', 'W', 'o', 'r', 'd', 's', '!']
^
['H', 'e', 'y', ' ', 'l', 'a', 'p', ' ', 'W', 'o', 'r', 'd', 's', '!']
^
anticipo per carattere successivo ('p') e copiare char
['H', 'e', 'y', ' ', 'l', 'a', 'p', ' ', 'W', 'o', 'r', 'd', 's', '!']
->^
char = 'p'
quando è stato rimosso il 'e' tutti i personaggi afte r la 'e' si è spostata di un posto a sinistra, quindi era come se lo remove
avanzi il puntatore. Il risultato è che hai saltato oltre la 'a'.
In generale, è necessario evitare di modificare gli elenchi durante l'iterazione su di essi. È meglio costruire una nuova lista da zero, e le comprovate liste di Python sono lo strumento perfetto per farlo. Per esempio.
print ''.join([char for char in "Hey look Words" if char.lower() not in "aeiou"])
Ma se non avete imparato a conoscere ancora comprensioni, il modo migliore è probabilmente:
text = "Hey look Words!"
def anti_vowel(text):
textlist = list(text)
new_textlist = []
for char in textlist:
if char.lower() not in 'aeiou':
new_textlist.append(char)
return "".join(new_textlist)
print anti_vowel(text)
Test e quindi rimuovendo ha una complessità N^2: è sufficiente rimuovere il carattere, se è presente o meno ... (o utilizzare altre soluzioni suggerite) – Don
@Don: O (n^2) dove n è cosa, la lunghezza del testo di input? – LarsH
'remove_vowels' sarebbe un nome migliore di' anti_vowel' –