从字符串中删除一组字符

234
我想在Python中删除字符串中的字符:
我想在Python中删掉一个字符串中的某些字符:
string.replace(',', '').replace("!", '').replace(":", '').replace(";", '')...

但是我有许多字符需要删除。我考虑过一个列表。

list = [',', '!', '.', ';'...]
但是我该如何使用 list 来替换 string 中的字符呢?

6
请参考 https://dev59.com/a3I-5IYBdhLWcg3wTWj4,该网页提供了多种解决方案和精美的比较。 - Martijn de Milliano
很遗憾,Python(据说自带电池)没有直接处理这种用例的功能。PHP的函数str_replace可以做到 - 你可以将数组作为第一个参数传递,字符串作为第二个参数(http://php.net/manual/pl/function.str-replace.php)。 - JustAC0der
20个回答

281

如果您正在使用Python2且输入为字符串(不是Unicode),那么最好的方法是使用str.translate函数:

>>> chars_to_remove = ['.', '!', '?']
>>> subj = 'A.B!C?'
>>> subj.translate(None, ''.join(chars_to_remove))
'ABC'

否则,可以考虑以下选项:
A. 逐个字符迭代主题,省略不需要的字符并使用join函数连接结果列表:
>>> sc = set(chars_to_remove)
>>> ''.join([c for c in subj if c not in sc])
'ABC'

请注意,生成器版本''.join(c for c ...)的效率会更低。

B.即时创建正则表达式并使用空字符串进行re.sub替换:

>>> import re
>>> rx = '[' + re.escape(''.join(chars_to_remove)) + ']'
>>> re.sub(rx, '', subj)
'ABC'

(re.escape 确保像 ^] 这样的字符不会破坏正则表达式)。

C. 使用 translate 的映射变体

>>> chars_to_remove = [u'δ', u'Γ', u'ж']
>>> subj = u'AжBδCΓ'
>>> dd = {ord(c):None for c in chars_to_remove}
>>> subj.translate(dd)
u'ABC'

完整的测试代码和时间:

#coding=utf8

import re

def remove_chars_iter(subj, chars):
    sc = set(chars)
    return ''.join([c for c in subj if c not in sc])

def remove_chars_re(subj, chars):
    return re.sub('[' + re.escape(''.join(chars)) + ']', '', subj)

def remove_chars_re_unicode(subj, chars):
    return re.sub(u'(?u)[' + re.escape(''.join(chars)) + ']', '', subj)

def remove_chars_translate_bytes(subj, chars):
    return subj.translate(None, ''.join(chars))

def remove_chars_translate_unicode(subj, chars):
    d = {ord(c):None for c in chars}
    return subj.translate(d)

import timeit, sys

def profile(f):
    assert f(subj, chars_to_remove) == test
    t = timeit.timeit(lambda: f(subj, chars_to_remove), number=1000)
    print ('{0:.3f} {1}'.format(t, f.__name__))

print (sys.version)
PYTHON2 = sys.version_info[0] == 2

print ('\n"plain" string:\n')

chars_to_remove = ['.', '!', '?']
subj = 'A.B!C?' * 1000
test = 'ABC' * 1000

profile(remove_chars_iter)
profile(remove_chars_re)

if PYTHON2:
    profile(remove_chars_translate_bytes)
else:
    profile(remove_chars_translate_unicode)

print ('\nunicode string:\n')

if PYTHON2:
    chars_to_remove = [u'δ', u'Γ', u'ж']
    subj = u'AжBδCΓ'
else:
    chars_to_remove = ['δ', 'Γ', 'ж']
    subj = 'AжBδCΓ'

subj = subj * 1000
test = 'ABC' * 1000

profile(remove_chars_iter)

if PYTHON2:
    profile(remove_chars_re_unicode)
else:
    profile(remove_chars_re)

profile(remove_chars_translate_unicode)

结果:

2.7.5 (default, Mar  9 2014, 22:15:05) 
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)]

"plain" string:

0.637 remove_chars_iter
0.649 remove_chars_re
0.010 remove_chars_translate_bytes

unicode string:

0.866 remove_chars_iter
0.680 remove_chars_re_unicode
1.373 remove_chars_translate_unicode

---

3.4.2 (v3.4.2:ab2c023a9432, Oct  5 2014, 20:42:22) 
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)]

"plain" string:

0.512 remove_chars_iter
0.574 remove_chars_re
0.765 remove_chars_translate_unicode

unicode string:

0.817 remove_chars_iter
0.686 remove_chars_re
0.876 remove_chars_translate_unicode

作为一个旁注,remove_chars_translate_bytes的数据可能会让我们猜测为什么该行业如此长时间不愿采用Unicode。

5
第二种方法会引发一个错误TypeError:translate()接受一个参数(给出了2个)。显然,它需要将字典作为参数传入。 - antonavy
@antonavy - 第二个解决方案确实可行 - 但仅适用于非Unicode字符串(需要使用不同的translate()函数)。 - FuzzyAmi

120
你可以使用 str.translate() 方法:
s.translate(None, ",!.;")

例子:

>>> s = "asjo,fdjk;djaso,oio!kod.kjods;dkps"
>>> s.translate(None, ",!.;")
'asjofdjkdjasooiokodkjodsdkps'

22
@thg435:没有人要求这个,但是无论如何:s.translate(dict.fromkeys(map(ord, u",!.;"))) - Sven Marnach
3
(这个和@PraveenGollakota的)同时回答正是@Laura所要求的,并且应该是首选答案。 - hobs
11
为什么Python3会报错:TypeError: translate() takes exactly one argument (2 given)?为什么Python3会报TypeError错误?translate()函数只接受一个参数,但是这里给了两个参数。 - Gank
2
@Gank:unicode.translate() 方法的参数与 str.translate() 方法不同。请针对 Unicode 对象使用上面评论中提到的变体。 - Sven Marnach
@SvenMarnach,map(ord, u",!.;"))是什么?u代表unicode吗? - Jun
@Jun 这将ord()函数映射到Unicode字符串u",!.;"的所有字符上,结果是一个Unicode代码点列表(Python 2)或迭代器(Python 3)。在Python 2中,u表示Unicode字符串。在Python 3中,它是可选的,因为字符串默认为Unicode字符串(早期版本的Python 3甚至不支持u""语法)。 - Sven Marnach

39

如果您正在使用 python3 并寻找 translate 的解决方案 - 函数已更改,现在只需要一个参数而不是两个。

该参数是一个表格(可以是字典),其中每个键是要查找的 Unicode 码位(int),而值是替换内容(可以是 Unicode 码位或将键映射到字符串的内容)。

以下是用法示例:

>>> list = [',', '!', '.', ';']
>>> s = "This is, my! str,ing."
>>> s.translate({ord(x): '' for x in list})
'This is my string'

37
您可以使用 translate 方法。
s.translate(None, '!.;,')

18
''.join(c for c in myString if not c in badTokens)

在类似情况下有用,不基于字符和字符串 +1 - Wolf

11

为什么不使用一个简单的循环?

for i in replace_list:
    string = string.replace(i, '')

此外,避免将列表命名为“list”。这会覆盖内置函数list


9

使用正则表达式的另一种方法:

''.join(re.split(r'[.;!?,]', s))

6
你可以使用类似这样的东西。
def replace_all(text, dic):
  for i, j in dic.iteritems():
    text = text.replace(i, j)
  return text

这段代码不是我自己写的,来自这里。这是一篇非常好的文章,深入讨论了如何用Python进行多词或字符替换。


5

从以下字符串中删除*%,& @!:

s = "this is my string,  and i will * remove * these ** %% "
new_string = s.translate(s.maketrans('','','*%,&@!'))
print(new_string)

# output: this is my string  and i will  remove  these  

  1. maketrans(x,y,z):第三个参数是用于替换的。x、y 在此处为空,因此不进行任何更改。只有带有 z 的字符被删除。
  2. translate():返回一个字符串,其中每个字符都映射到其在翻译表中对应的字符(这里是从 maketrans 函数中获取的)。
- Aybid

5
简单方法,
import re
str = 'this is string !    >><< (foo---> bar) @-tuna-#   sandwich-%-is-$-* good'

// condense multiple empty spaces into 1
str = ' '.join(str.split()

// replace empty space with dash
str = str.replace(" ","-")

// take out any char that matches regex
str = re.sub('[!@#$%^&*()_+<>]', '', str)

输出结果:

this-is-string--foo----bar--tuna---sandwich--is---good

(该文本为原始文本,无需翻译)

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