使用Python中的循环删除列表中的项目

时间:2014-08-15 12:23:54

标签: python

我对编程很新,并且已经开始使用Python了。我正在解决各种问题,以便更好地理解我的理解。

我正在尝试定义一个从字符串中删除元音的函数。这就是我的尝试:

def anti_vowel(text):
    new = []
    for i in range(len(text)):
        new.append(text[i])
    print new
    for x in new:
        if x == "e" or x == "E" or x == "a" or x == "A" or x == "i" or x == "I" or x == "o" or x == "O" or x == "u" or x == "U":
            new.remove(x)
    return "".join(new)

这是从字符串的第一个单词中删除元音,但不是最后一个单词:

例如:

anti_vowel("Hey look words!")    
returns: "Hy lk words!"

有人可以解释我哪里出错了所以我可以从中吸取教训吗?

谢谢:)

5 个答案:

答案 0 :(得分:5)

should not delete items from a list while iterating through it。你会在Stack Overflow上找到很多帖子来解释原因。

我会使用filter函数

>>> vowels = 'aeiouAEIOU'
>>> myString = 'This is my string that has vowels in it'
>>> filter(lambda i : i not in vowels, myString)
'Ths s my strng tht hs vwls n t'

作为一个函数编写,这将是

def anti_vowel(text):
    vowels = 'aeiouAEIOU'
    return filter(lambda letter : letter not in vowels, text)

测试

>>> anti_vowel(myString)
'Ths s my strng tht hs vwls n t'

答案 1 :(得分:2)

你好像已经向后看了一下。首先,请注意:

new = []
for i in range(len(text)):
    new.append(text[i])

只是:

new = list(text)

其次,为什么不在append之前检查,而不是之后检查?然后你只需要迭代一次字符。这可能是:

def anti_vowel(text):
    """Remove all vowels from the supplied text.""" # explanatory docstring
    non_vowels = [] # clear variable names
    vowels = set("aeiouAEIOU") # sets allow fast membership tests
    for char in text: # iterate directly over characters, no need for 'i'
        if char not in vowels: # test membership of vowels
            non_vowels.append(char) # add non-vowels only
    return "".join(non_vowels)

一个简单的例子:

>>> anti_vowel("Hey look words!")
'Hy lk wrds!'

这进一步简化为list comprehension

def anti_vowel(text):
    """Remove all vowels from the supplied text."""
    vowels = set("aeiouAEIOU")
    return "".join([char for char in text if char not in vowels])

答案 2 :(得分:1)

您可以使用列表comp:

def anti_vowel(text):
    vowels = 'aeiouAEIOU'
    return "".join([x for x in text if x not in vowels])
print anti_vowel("Hey look words!")
Hy lk wrds!

列表理解过滤单词中的元音。

答案 3 :(得分:0)

你也可以简洁地理解它:

def anti_vowel(text):
    return ''.join(ch for ch in text if ch.upper() not in 'AEIOU')

答案 4 :(得分:0)

迭代是一种索引操作。当您在迭代它时从列表中删除项目时,您实际上更改了列表中您删除的项目后面的每个项目的索引。循环遍历列表时

['h','e','y',' ','l','o','o','k',' ','w','o','r','d','s']

同时删除'aeiou'中的项目,在循环的第二次迭代中,您从列表中删除'e',然后用

删除左侧
['h','y',' ','l','o','o','k',' ','w','o','r','d','s']

然后在第三次迭代中,而不是在最初位于第三位置的y上测试你的if语句,而不是在' '上测试它,这就是修改后的清单的第三个位置。

mylist.remove(x)

将在x中搜索mylist的第一个匹配值并将其删除。当您的循环到达列表中的第一个'o'时,它会将其删除,从而将'o'的索引更改为-1。在循环的下一次迭代中,它会查看'k'而不是后续的'o'

但是,为什么你的函数会删除前两个'o'而不是最后一个?

您的循环查看了第一个'o',而不是第二个'o',并查看了第三个'o'。总的来说,你的循环找到了'o'的两个匹配项,并在两者上执行了remove函数。同样,由于remove函数会在列表中找到第一个匹配项并将其删除,这就是为什么它删除了前两个'o',尽管删除了第二个'o'你的循环实际上正在迭代第三个'o'

你很幸运在连续元音的字符串上完成了这个测试。如果你在没有连续元音的字符串上完成它,你就可以删除所有带有你的功能的元音,它本来可以按你的意图工作。