在Python中去除字符串中的非字母数字字符
如何用Python去掉字符串中所有非字母数字的字符,最好的方法是什么?
在这个问题的PHP版本中提出的解决方案可能经过一些小调整后也能用,但我觉得它们看起来不太“符合Python风格”。
顺便说一下,我不仅仅想去掉句号和逗号(还有其他标点符号),还想去掉引号、括号等等。
16 个回答
80
使用 str.translate()
方法。
假设你会经常这样做:
首先,创建一个包含你想删除的所有字符的字符串:
delchars = ''.join(c for c in map(chr, range(256)) if not c.isalnum())
每当你想压缩一个字符串时:
scrunched = s.translate(None, delchars)
设置的成本可能和 re.compile
相比还不错;而后续的成本要低得多:
C:\junk>\python26\python -mtimeit -s"import string;d=''.join(c for c in map(chr,range(256)) if not c.isalnum());s=string.printable" "s.translate(None,d)"
100000 loops, best of 3: 2.04 usec per loop
C:\junk>\python26\python -mtimeit -s"import re,string;s=string.printable;r=re.compile(r'[\W_]+')" "r.sub('',s)"
100000 loops, best of 3: 7.34 usec per loop
注意:使用 string.printable
作为基准数据会让模式 '[\W_]+'
有不公平的优势;因为所有的非字母数字字符都在一块……在典型的数据中,可能需要做的不止一次替换:
C:\junk>\python26\python -c "import string; s = string.printable; print len(s),repr(s)"
100 '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'
如果你让 re.sub
多做一点工作,会发生这样的情况:
C:\junk>\python26\python -mtimeit -s"d=''.join(c for c in map(chr,range(256)) if not c.isalnum());s='foo-'*25" "s.translate(None,d)"
1000000 loops, best of 3: 1.97 usec per loop
C:\junk>\python26\python -mtimeit -s"import re;s='foo-'*25;r=re.compile(r'[\W_]+')" "r.sub('',s)"
10000 loops, best of 3: 26.4 usec per loop
379
正则表达式来帮忙:
import re
re.sub(r'\W+', '', your_string)
在Python中,
'\W'
的意思是[^a-zA-Z0-9_]
,这表示排除了所有的数字
、字母
和_
符号。
455
我出于好奇,测试了一些函数的运行时间。在这些测试中,我从字符串 string.printable
中去掉了非字母数字的字符(这个字符串是内置的 string
模块的一部分)。我发现使用编译后的 '[\W_]+'
和 pattern.sub('', str)
的速度是最快的。
$ python -m timeit -s \
"import string" \
"''.join(ch for ch in string.printable if ch.isalnum())"
10000 loops, best of 3: 57.6 usec per loop
$ python -m timeit -s \
"import string" \
"filter(str.isalnum, string.printable)"
10000 loops, best of 3: 37.9 usec per loop
$ python -m timeit -s \
"import re, string" \
"re.sub('[\W_]', '', string.printable)"
10000 loops, best of 3: 27.5 usec per loop
$ python -m timeit -s \
"import re, string" \
"re.sub('[\W_]+', '', string.printable)"
100000 loops, best of 3: 15 usec per loop
$ python -m timeit -s \
"import re, string; pattern = re.compile('[\W_]+')" \
"pattern.sub('', string.printable)"
100000 loops, best of 3: 11.2 usec per loop