我试图使用Python从字符串中删除特定字符。这是我现在使用的代码。不幸的是,它似乎对字符串没有做任何事情。

for char in line:
    if char in " ?.!/;:":
        line.replace(char,'')

我如何正确地做到这一点?


当前回答

Python中的字符串是不可变的(不能更改)。因此,line.replace(…)的作用只是创建一个新字符串,而不是更改旧字符串。您需要将其重新绑定(赋值)到行,以便使该变量具有新的值,并删除那些字符。

而且,你做的方法相对来说会比较慢。对于有经验的python编程者来说,这也可能会有点困惑,他们会看到一个双嵌套结构,并认为正在发生更复杂的事情。

从Python 2.6和更新的Python 2开始。x版本*,你可以使用str.translate,(见下面的Python 3答案):

line = line.translate(None, '!@#$')

或者用re.sub替换正则表达式

import re
line = re.sub('[!@#$]', '', line)

括号内的字符构成一个字符类。行中属于该类的任何字符都被替换为要sub的第二个参数:空字符串。

Python 3答案

在Python 3中,字符串是Unicode。你得翻译得有点不同。Kevpie在其中一个答案的注释中提到了这一点,str.translate的文档中也提到了这一点。

在调用Unicode字符串的translate方法时,不能传递上面使用的第二个参数。也不能将None作为第一个参数。相反,您传递一个翻译表(通常是字典)作为唯一的参数。这个表将字符的序号值(即对它们调用ord的结果)映射到应该替换它们的字符的序号值,或者对我们来说有用的是none,表示它们应该被删除。

因此,要对Unicode字符串执行上述操作,您可以调用类似于

translation_table = dict.fromkeys(map(ord, '!@#$'), None)
unicode_line = unicode_line.translate(translation_table)

这里使用dict.fromkeys和map简洁地生成包含

{ord('!'): None, ord('@'): None, ...}

甚至更简单,正如另一个答案所说,在适当的地方创建翻译表:

unicode_line = unicode_line.translate({ord(c): None for c in '!@#$'})

或者,正如Joseph Lee提出的那样,使用str.maketrans创建相同的翻译表:

unicode_line = unicode_line.translate(str.maketrans('', '', '!@#$'))

*为了与早期的python兼容,你可以创建一个“null”转换表来代替None:

import string
line = line.translate(string.maketrans('', ''), '!@#$')

这里的字符串。Maketrans用于创建一个转换表,它只是一个包含序数为0到255的字符的字符串。

其他回答

令我惊讶的是,还没有人推荐使用内置的过滤功能。

    import operator
    import string # only for the example you could use a custom string

    s = "1212edjaq"

假设我们想过滤掉所有不是数字的东西。使用过滤器内置方法“…等效于生成器表达式(item for item在可迭代if函数(item)中)"[Python 3 Builtins: Filter]

    sList = list(s)
    intsList = list(string.digits)
    obj = filter(lambda x: operator.contains(intsList, x), sList)))

在Python 3中返回

    >>  <filter object @ hex>

要得到打印的字符串,

    nums = "".join(list(obj))
    print(nums)
    >> "1212"

我不确定过滤器在效率方面的排名,但在做列表理解等时,知道如何使用是一件好事。

更新

从逻辑上讲,既然过滤器可以工作,你也可以使用列表理解,从我所读到的,它应该更有效,因为lambdas是编程函数世界的华尔街对冲基金经理。另一个优点是它是一个单行程序,不需要任何导入。例如,使用上面定义的字符串's',

      num = "".join([i for i in s if i.isdigit()])

就是这样。返回值将是原始字符串中所有数字组成的字符串。

如果你有一个特定的可接受/不可接受字符列表,你只需要调整列表理解的' If '部分。

      target_chars = "".join([i for i in s if i in some_list]) 

或者,

      target_chars = "".join([i for i in s if i not in some_list])
>>> s = 'a1b2c3'
>>> ''.join(c for c in s if c not in '123')
'abc'

你可以使用re模块的正则表达式替换。使用^表达式可以准确地从字符串中选择想要的内容。

    import re
    text = "This is absurd!"
    text = re.sub("[^a-zA-Z]","",text) # Keeps only Alphabets
    print(text)

输出结果将是“这是荒谬的”。只有在^符号之后指定的内容才会出现。

试试这个:

def rm_char(original_str, need2rm):
    ''' Remove charecters in "need2rm" from "original_str" '''
    return original_str.translate(str.maketrans('','',need2rm))

这个方法在python3中很有效

您还可以使用函数来替换不同类型的正则表达式或使用列表的其他模式。这样,您就可以混合正则表达式、字符类和真正基本的文本模式。当您需要替换大量元素(如HTML元素)时,它非常有用。

*注意:适用于Python 3.x

import re  # Regular expression library


def string_cleanup(x, notwanted):
    for item in notwanted:
        x = re.sub(item, '', x)
    return x

line = "<title>My example: <strong>A text %very% $clean!!</strong></title>"
print("Uncleaned: ", line)

# Get rid of html elements
html_elements = ["<title>", "</title>", "<strong>", "</strong>"]
line = string_cleanup(line, html_elements)
print("1st clean: ", line)

# Get rid of special characters
special_chars = ["[!@#$]", "%"]
line = string_cleanup(line, special_chars)
print("2nd clean: ", line)

在函数string_cleanup中,它以字符串x和未修饰的列表作为参数。对于元素或模式列表中的每一项,如果需要替代品,就会进行替换。

输出:

Uncleaned:  <title>My example: <strong>A text %very% $clean!!</strong></title>
1st clean:  My example: A text %very% $clean!!
2nd clean:  My example: A text very clean