python - Loop "Forgets" to Remove Some Items -
this question has answer here:
in code trying create function anti_vowel remove vowels (aeiouaeiou) string. think should work ok, when run it, sample text "hey words!" returned "hy lk words!". "forgets" remove last 'o'. how can be?
text = "hey words!" def anti_vowel(text): textlist = list(text) char in textlist: if char.lower() in 'aeiou': textlist.remove(char) return "".join(textlist) print anti_vowel(text)
you're modifying list you're iterating over, bound result in unintuitive behavior. instead, make copy of list don't remove elements you're iterating through.
for char in textlist[:]: #shallow copy of list # etc
to clarify behavior you're seeing, check out. put print char, textlist
@ beginning of (original) loop. you'd expect, perhaps, print out string vertically, alongside list, you'll this:
h ['h', 'e', 'y', ' ', 'l', 'o', 'o', 'k', ' ', 'w', 'o', 'r', 'd', 's', '!'] e ['h', 'e', 'y', ' ', 'l', 'o', 'o', 'k', ' ', 'w', 'o', 'r', 'd', 's', '!'] ['h', 'y', ' ', 'l', 'o', 'o', 'k', ' ', 'w', 'o', 'r', 'd', 's', '!'] # ! l ['h', 'y', ' ', 'l', 'o', 'o', 'k', ' ', 'w', 'o', 'r', 'd', 's', '!'] o ['h', 'y', ' ', 'l', 'o', 'o', 'k', ' ', 'w', 'o', 'r', 'd', 's', '!'] k ['h', 'y', ' ', 'l', 'o', 'k', ' ', 'w', 'o', 'r', 'd', 's', '!'] # problem!! ['h', 'y', ' ', 'l', 'o', 'k', ' ', 'w', 'o', 'r', 'd', 's', '!'] w ['h', 'y', ' ', 'l', 'o', 'k', ' ', 'w', 'o', 'r', 'd', 's', '!'] o ['h', 'y', ' ', 'l', 'o', 'k', ' ', 'w', 'o', 'r', 'd', 's', '!'] d ['h', 'y', ' ', 'l', 'k', ' ', 'w', 'o', 'r', 'd', 's', '!'] s ['h', 'y', ' ', 'l', 'k', ' ', 'w', 'o', 'r', 'd', 's', '!'] ! ['h', 'y', ' ', 'l', 'k', ' ', 'w', 'o', 'r', 'd', 's', '!'] hy lk words!
so what's going on? nice for x in y
loop in python syntactic sugar: still accesses list elements index. when remove elements list while iterating on it, start skipping values (as can see above). result, never see second o
in "look"
; skip on because index has advanced "past" when deleted previous element. then, when o
in "words"
, go remove first occurrence of 'o'
, 1 skipped before.
as others have mentioned, list comprehensions better (cleaner, clearer) way this. make use of fact python strings iterable:
def remove_vowels(text): # function names should start verbs! :) return ''.join(ch ch in text if ch.lower() not in 'aeiou')
Comments
Post a Comment