You're iterating over a list and deleting elements from it at the same time.
First, I need to make sure you clearly understand the role of char
in for char in textlist: ...
. Take the situation where we have reached the letter 'l'. The situation is not like this:
['H', 'e', 'y', ' ', 'l', 'o', 'o', 'k', ' ', 'W', 'o', 'r', 'd', 's', '!']
^
char
There is no link between char
and the position of the letter 'l' in the list. If you modify char
, the list will not be modified. The situation is more like this:
['H', 'e', 'y', ' ', 'l', 'o', 'o', 'k', ' ', 'W', 'o', 'r', 'd', 's', '!']
^
char = 'l'
Notice that I've kept the ^
symbol. This is the hidden pointer that the code managing the for char in textlist: ...
loop uses to keep track of its position in the loop. Every time you enter the body of the loop, the pointer is advanced, and the letter referenced by the pointer is copied into char
.
Your problem occurs when you have two vowels in succession. I'll show you what happens from the point where you reach 'l'. Notice that I've also changed the word "look" to "leap", to make it clearer what's going on:
advance pointer to next character ('l') and copy to char
['H', 'e', 'y', ' ', 'l', 'e', 'a', 'p', ' ', 'W', 'o', 'r', 'd', 's', '!']
-> ^
char = 'l'
char
('l') is not a vowel, so do nothing
advance pointer to next character ('e') and copy to char
['H', 'e', 'y', ' ', 'l', 'e', 'a', 'p', ' ', 'W', 'o', 'r', 'd', 's', '!']
-> ^
char = 'e'
char
('e') is a vowel, so delete the first occurrence of char
('e')
['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', '!']
^
advance pointer to next character ('p') and copy to char
['H', 'e', 'y', ' ', 'l', 'a', 'p', ' ', 'W', 'o', 'r', 'd', 's', '!']
-> ^
char = 'p'
When you removed the 'e' all the characters after the 'e' moved one place to the left, so it was as if remove
had advanced the pointer. The result is that you skipped past the 'a'.
In general, you should avoid modifying lists while iterating over them. It's better to construct a new list from scratch, and Python's list comprehensions are the perfect tool for doing this. E.g.
print ''.join([char for char in "Hey look Words" if char.lower() not in "aeiou"])
But if you haven't learnt about comprehensions yet, the best way is probably:
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)