您正在修改的列表你遍历,这是必然会导致一些不直观的行为。相反,制作一份清单的副本,以便不会从要迭代的内容中移除元素。
for char in textlist[:]: #shallow copy of the list
# etc
为了澄清你所看到的行为,检查了这一点。将print char, textlist
放在您的(原始)循环的开头。你会想到,也许,这将垂直打印出你的字符串,旁边的列表,但你实际上会得到是这样的:
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!
那么这是怎么回事? Python中好的for x in y
循环实际上只是语法糖:它仍然通过索引访问列表元素。因此,当您从列表中移除元素时,您将开始跳过值(如上所示)。因此,你永远不会看到"look"
中的第二个o
;你可以跳过它,因为当你删除前一个元素时,索引已经提前“过去”了。然后,当您到达"Words"
中的o
时,您将删除第一个出现'o'
,这是您之前跳过的。
正如其他人所说的,列表解析可能是一种更好(更清晰,更清晰)的方式来做到这一点。利用的事实,Python中的字符串是可迭代:
def remove_vowels(text): # function names should start with verbs! :)
return ''.join(ch for ch in text if ch.lower() not in 'aeiou')
测试,然后除去有N^2的复杂性:刚除去炭,无论存在或不存在...(或使用其他建议的解决方案) – Don
@Don:为O(n^2),其中n什么是输入文本的长度? – LarsH
'remove_vowels'会比'anti_vowel'更好的名字 –