循环“忘记"删除一些项目 [英] Loop "Forgets" to Remove Some Items

查看:28
本文介绍了循环“忘记"删除一些项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在这段代码中,我试图创建一个函数 anti_vowel,它将从字符串中删除所有元音 (aeiouAEIOU).我认为它应该工作正常,但是当我运行它时,示例文本Hey look Words!"返回为Hy lk Words!".它忘记"删除最后一个o".这怎么可能?

in this code I am trying to create a function anti_vowel that will remove all vowels (aeiouAEIOU) from a string. I think it should work ok, but when I run it, the sample text "Hey look Words!" is returned as "Hy lk Words!". It "forgets" to remove the last 'o'. How can this be?

text = "Hey look Words!"

def anti_vowel(text):

    textlist = list(text)

    for char in textlist:
        if char.lower() in 'aeiou':
            textlist.remove(char)

    return "".join(textlist)

print anti_vowel(text)

推荐答案

您正在修改正在迭代的列表,这必然会导致一些不直观的行为.相反,制作列表的副本,这样您就不会从正在迭代的内容中删除元素.

You're modifying the list you're iterating over, which is bound to result in some unintuitive behavior. Instead, make a copy of the list so you don't remove elements from what you're iterating through.

for char in textlist[:]: #shallow copy of the list
    # etc

<小时>

要澄清您看到的行为,请查看此内容.将 print char, textlist 放在(原始)循环的开头.您可能希望这会在列表旁边垂直打印出您的字符串,但您实际得到的是:


To clarify the behavior you're seeing, check this out. Put print char, textlist at the beginning of your (original) loop. You'd expect, perhaps, that this would print out your string vertically, alongside the list, but what you'll actually get is 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!

那是怎么回事?Python 中很好的 for x in y 循环实际上只是语法糖:它仍然通过索引访问列表元素.因此,当您在迭代列表时从列表中删除元素时,您开始跳过值(如上所示).结果,您永远不会在 "look" 中看到第二个 o;你跳过它是因为当你删除前一个元素时索引已经超过"它了.然后,当您到达 "Words" 中的 o 时,您将删除第一次出现的 'o',即你之前跳过了.

So what's going on? The nice for x in y loop in Python is really just syntactic sugar: it still accesses list elements by index. So when you remove elements from the list while iterating over it, you start skipping values (as you can see above). As a result, you never see the second o in "look"; you skip over it because the index has advanced "past" it when you deleted the previous element. Then, when you get to the o in "Words", you go to remove the first occurrence of 'o', which is the one you skipped before.

正如其他人所提到的,列表推导式可能是一种更好(更清晰、更清晰)的方式来做到这一点.利用 Python 字符串是可迭代的这一事实:

As others have mentioned, list comprehensions are probably an even better (cleaner, clearer) way to do this. Make use of the fact that Python strings are iterable:

def remove_vowels(text): # function names should start with verbs! :)
    return ''.join(ch for ch in text if ch.lower() not in 'aeiou')

这篇关于循环“忘记"删除一些项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆