从字符串中移除字符 Python

4

我正在尝试编写一个函数,以消除给定字符串中的元音字母,但它似乎没有按照预期的方式运行...

def anti_vowel(text):
    for c in text:
        if c in "aeiouAEIOU":
            no_vowel = text.replace(c, '')
    return no_vowel
print(anti_vowel('Hello World')

所以不是打印输出
Hll Wrld

它打印输出

Hell Wrld  

感谢您(提前)的帮助。

no_vowel 定义在哪里? - Christian Dean
4个回答

9
问题在于no_vowel仅具有text.replace(c, '')最后一次执行的值。另一个问题是,只有在实际存在需要删除的元音字母时,no_vowel才会获得值;这段代码将无法处理anti_vowel('vwllss')。此外,在调用str.replace()之前不必检查字符是否包含在文本中。
以下是修改后的代码:
def anti_vowel(text):
    for vowel in "aeiouAEIOU":
        text = text.replace(vowel, '')
    return text
print(anti_vowel('Hello World'))

正如其他人所指出的,另一种方法是以不同的方式编写代码:

def anti_vowel(text):
    ''.join(c for c in text if c not in 'aeiouAEIOU')

请在 ''.join() 中使用生成表达式而不是列表推导式;这样的列表推导式会不必要地分配内存。

1
答案不错,但最后一句话并不正确。每当使用 str.join 时,总是要使用列表推导式。join 的参数将始终转换为一个序列,因此生成器表达式比列表推导式更慢且不如其内存高效。 - MSeifert
@MSeifert 你有支持那个说法的参考资料吗? - dr. Sybren
参考Python源代码中的str.join函数:https://github.com/python/cpython/blob/master/Objects/unicodeobject.c#L9868,还可以查看我的其他评论:https://dev59.com/W53ha4cB1Zd3GeqPRUHd#41083246?noredirect=1#comment69372767_41083255 - MSeifert
1
是的,这个“only”表明它被转换为一个序列。生成器不是序列,将生成器转换为序列比起一开始就创建序列会慢得多。 - MSeifert

5
您可以使用string.translate()来实现此功能。例如:
def anti_vowel(text):
  return text.translate(None, "aeiouAEIOU")

print(anti_vowel("hello world"))

Python 3版本中,delete参数已经被删除了,但你仍然可以通过将一个字符映射到None来实现。

def anti_vowel_py3(text):
   return text.translate({ord(i): None for i in "aeiouAEIOU"})

print(anti_vowel_py3("hello world"))

2

您的代码无法正常工作,因为在每次迭代时,您都会重新将no_vowel与整个文本分配,并且您迭代了文本的字母,而这不应该,因为replace已经执行了此操作。您应该这样编写:

def anti_vowel(text):
    no_vowel = text
    for c in 'aeiouAEIOU':
        no_vowel = no_vowel.replace(c, '')

    return no_vowel

或者,您可以使用列表推导式。更符合Python编程风格且运行速度更快:

def anti_vowel(text):
    return ''.join([c for c in text if c not in 'aeiouAEIOU])

这个不起作用,它返回"['H', 'l', 'l', ' ', 'W', 'r', 'l', 'd']"。这个可以:''.join(c for c in text if c not in 'aeiouAEIOU') - dr. Sybren
你需要关闭那个字符串。 - Christian Dean
@leaf 因为 str.join 需要一个序列(而不是生成器),所以当它被转换为列表时,使用生成器只会增加不必要的开销。 - MSeifert
1
@MSeifert也许你是对的,但我仍然不太理解使用生成器为何会低效。 - Christian Dean
@leaf 只有在您不需要所有元素或随机访问时,生成器才有用。 您可以查看源代码(https://github.com/python/cpython/blob/master/Objects/unicodeobject.c#L9868)和文档(https://docs.python.org/3/c-api/sequence.html#c.PySequence_Fast)。 在这种情况下,这相当于 list(generator),这肯定比使用列表推导式慢。 - MSeifert
@MSeifert 在查看了 Github 上的源代码后,看起来你是正确的。感谢你让我知道。 - Christian Dean

1

在循环的每一次迭代中,文本是“Hello World”,而文本的最后一个元音字母是“o”,因此在循环结束时,no_vowel 就变成了“Hell Wrld”。

在 Python 2.7 中,使用 translate 方法代替。这是官方文件:

translate(...)

 S.translate(table [,deletechars]) -> string

 Return a copy of the string S, where all characters occurring
 in the optional argument deletechars are removed, and the
 remaining characters have been mapped through the given
 translation table, which must be a string of length 256 or None.

 If the table argument is None, no translation is applied and
 the operation simply removes the characters in deletechars.

"Hello World".translate(None, "aeiouAEIOU") 可以得到正确的结果 "Hll Wrld"

此外,re.sub('[aeiouAEIOU]', "", "Hello World") 在 Python 2.7 和 Python 3 中都可以使用。


这个不起作用,并导致“TypeError”:translate()只需要一个参数(给出了2个)。 - dr. Sybren
@Sybren 这在Python2.7中可行,但在Python3中,方法translate的参数deletechars已经被删除了。 - smilingwang
1
@Sybren re.sub('[aeiouAEIOU]', "", "Hello World") 可以在 Python2.7 和 Python3 中使用。 - smilingwang

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接