Loop “Forgets” to Remove Some Items
在这段代码中,我试图创建一个反元音函数,它将删除字符串中的所有元音(aeiouaeiou)。我认为它应该可以工作,但当我运行它时,示例文本"嘿,看单词!"返回为"hy-lk words!".它"忘记"删除最后一个"o"。怎么会这样?
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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) |
你的列表迭代修改过你,这是有时在一些unintuitive行为的结果。而不是创建一个复制列表,所以你不要删除元素从你再通过迭代。
1 2 | for char in textlist[:]: #shallow copy of the list # etc |
要澄清的行为,你看到的,看看这个。在你开始把
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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的字符串:
1 2 | def remove_vowels(text): # function names should start with verbs! :) return ''.join(ch for ch in text if ch.lower() not in 'aeiou') |
其他答案告诉你为什么你的年龄
用途:
1 2 3 | vowels = 'aeiou' vowels += vowels.upper() text.translate(None, vowels) |
在删除所有字符列在第二的论点。
演示:
1 2 3 4 5 6 7 8 | >>> text ="Hey look Words!" >>> vowels = 'aeiou' >>> vowels += vowels.upper() >>> text.translate(None, vowels) 'Hy lk Wrds!' >>> text = 'The Quick Brown Fox Jumps Over The Lazy Fox' >>> text.translate(None, vowels) 'Th Qck Brwn Fx Jmps vr Th Lzy Fx' |
在Python(Python
1 2 3 4 5 | # Python 3 code vowels = 'aeiou' vowels += vowels.upper() vowels_table = dict.fromkeys(map(ord, vowels)) text.translate(vowels_table) |
所以,你可以使用静态方法
1 2 3 | vowels = 'aeiou' vowels += vowels.upper() text.translate(text.maketrans('', '', vowels)) |
引证:从文档
Note: There is a subtlety when the sequence is being modified by the
loop (this can only occur for mutable sequences, i.e. lists). An
internal counter is used to keep track of which item is used next, and
this is incremented on each iteration. When this counter has reached
the length of the sequence the loop terminates. This means that if the
suite deletes the current (or a previous) item from the sequence, the
next item will be skipped (since it gets the index of the current item
which has already been treated). Likewise, if the suite inserts an
item in the sequence before the current item, the current item will be
treated again the next time through the loop. This can lead to nasty
bugs that can be avoided by making a temporary copy using a slice of
the whole sequence, e.g.,
1 2 | for x in a[:]: if x < 0: a.remove(x) |
iterate over a浅表
一个
我们以简单的例子:
1 2 3 4 5 6 7 | >>> text ="whoops" >>> textlist = list(text) >>> textlist ['w', 'h', 'o', 'o', 'p', 's'] for char in textlist: if char.lower() in 'aeiou': textlist.remove(char) |
1:迭代指数= 0。
它是在
2:迭代指数= 1。
它是在
3:迭代指数= 2。
它是在
现在
1 2 | 0 1 2 3 4 `['w', 'h', 'o', 'p', 's']` |
你可以看到
迭代指数= 4:3。
它是在
…………………
修复:
iterate over a浅复制固定这个问题列表:
1 2 3 | for char in textlist[:]: #note the [:] if char.lower() in 'aeiou': textlist.remove(char) |
其他的选择:
发展战略:
一个系统和一
1 2 3 | vowels = 'aeiou' text ="Hey look Words!" return"".join([char for char in text if char.lower() not in vowels]) |
正则表达式:
1 2 3 4 | >>> import re >>> text ="Hey look Words!" >>> re.sub('[aeiou]', '', text, flags=re.I) 'Hy lk Wrds!' |
你是你修改过的数据的迭代。不要做。
1 | ''.join(x for x in textlist in x not in VOWELS) |
1 2 3 | text ="Hey look Words!" print filter(lambda x: x not in"AaEeIiOoUu", text) |
输出
1 | Hy lk Wrds! |
您正在迭代一个列表,同时从中删除元素。
首先,我需要确保您清楚地了解
1 2 3 | ['H', 'e', 'y', ' ', 'l', 'o', 'o', 'k', ' ', 'W', 'o', 'r', 'd', 's', '!'] ^ char |
1 2 3 | ['H', 'e', 'y', ' ', 'l', 'o', 'o', 'k', ' ', 'W', 'o', 'r', 'd', 's', '!'] ^ char = 'l' |
号
注意,我保留了
你的问题发生在你连续有两个元音的时候。我会告诉你从你到达"L"的地方发生了什么。请注意,我还将"look"改为"leap",以便更清楚地了解正在发生的事情:
将指针前进到下一个字符("l")并复制到EDOCX1[0]
1 2 3 | ['H', 'e', 'y', ' ', 'l', 'e', 'a', 'p', ' ', 'W', 'o', 'r', 'd', 's', '!'] -> ^ char = 'l' |
将指针前进到下一个字符("e")并复制到EDOCX1[0]
1 2 3 | ['H', 'e', 'y', ' ', 'l', 'e', 'a', 'p', ' ', 'W', 'o', 'r', 'd', 's', '!'] -> ^ char = 'e' |
。
1 2 3 4 5 6 7 8 9 10 11 | ['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', '!'] ^ |
将指针前进到下一个字符("P")并复制到EDOCX1[0]
1 2 3 | ['H', 'e', 'y', ' ', 'l', 'a', 'p', ' ', 'W', 'o', 'r', 'd', 's', '!'] -> ^ char = 'p' |
。
删除"e"后,所有"e"的字符都向左移动了一个位置,所以就好像
一般来说,在遍历列表时应避免修改列表。最好从头构建一个新的列表,而python的列表理解是实现这一点的完美工具。例如。
1 | print ''.join([char for char in"Hey look Words" if char.lower() not in"aeiou"]) |
。
但如果你还没有学会理解,最好的方法可能是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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) |
列表理解:
1 2 3 4 | vowels = 'aeiou' text = 'Hey look Words!' result = [char for char in text if char not in vowels] print ''.join(result) |
其他人可能已经在你的代码的问题。你的任务是不容易的表达A发电机的误差之和。
1 2 3 | >>> text ="Hey look Words!" >>> ''.join(c for c in text if c.lower() not in 'aeiou') 'Hy lk Wrds!' |
或
1 2 | >>> ''.join(c for c in text if c not in 'AaEeIiOoUu') 'Hy lk Wrds!' |
然而,
尽量不要在字符串上使用list()函数。这会使事情变得更加复杂。
与Java不同,在Python中,字符串被认为是数组。然后,尝试对loop和del关键字使用索引。
1 2 3 | for x in range(len(string)): if string[x].lower() in"aeiou": del string[x] |
您不应该从正在迭代的列表中删除项:但是,您可以使用列表理解语法从旧列表中创建新列表。在这种情况下,列表理解非常有用。你可以在这里阅读列表理解
因此,您的解决方案如下所示:
1 2 3 4 5 6 | text ="Hey look Words!" def anti_vowel(text): return"".join([char for char in list(text) if char.lower() not in 'aeiou']) print anti_vowel(text) |
。
很漂亮,不是吗:P