在 Python 2.* 中,迄今为止最快的方法是 .translate 方法:
>>> x='aaa12333bb445bb54b5b52'
>>> import string
>>> all=string.maketrans('','')
>>> nodigs=all.translate(all, string.digits)
>>> x.translate(all, nodigs)
'1233344554552'
>>>
string.maketrans 制作一个转换表(长度为 256 的字符串),在这种情况下与 ''.join(chr(x) for x in range(256)) 相同(制作速度更快;-)。 .translate 应用转换表(此处无关,因为 all 本质上表示身份)并删除第二个参数中存在的字符 - 关键部分。
.translate 在 Unicode 字符串(和 Python 3 中的字符串——我确实希望问题指定 Python 的哪个主要版本是感兴趣的!)上的工作方式非常不同——不是那么简单,没那么快,但仍然很实用。
回到 2.*,性能差异令人印象深刻...:
$ python -mtimeit -s'import string; all=string.maketrans("", ""); nodig=all.translate(all, string.digits); x="aaa12333bb445bb54b5b52"' 'x.translate(all, nodig)'
1000000 loops, best of 3: 1.04 usec per loop
$ python -mtimeit -s'import re; x="aaa12333bb445bb54b5b52"' 're.sub(r"\D", "", x)'
100000 loops, best of 3: 7.9 usec per loop
将速度提高 7-8 倍可不是小菜一碟,所以 translate 方法非常值得了解和使用。另一种流行的非 RE 方法...:
$ python -mtimeit -s'x="aaa12333bb445bb54b5b52"' '"".join(i for i in x if i.isdigit())'
100000 loops, best of 3: 11.5 usec per loop
比 RE 慢 50%,因此 .translate 方法比它快一个数量级以上。
在 Python 3 或 Unicode 中,您需要传递 .translate 一个映射(使用序号,而不是直接作为键的字符),该映射返回 None 来表示您要删除的内容。以下是删除“除几个字符之外的所有内容”的一种便捷方式:
import string
class Del:
def __init__(self, keep=string.digits):
self.comp = dict((ord(c),c) for c in keep)
def __getitem__(self, k):
return self.comp.get(k)
DD = Del()
x='aaa12333bb445bb54b5b52'
x.translate(DD)
也会发出'1233344554552'。但是,将其放入 xx.py 中,我们有...:
$ python3.1 -mtimeit -s'import re; x="aaa12333bb445bb54b5b52"' 're.sub(r"\D", "", x)'
100000 loops, best of 3: 8.43 usec per loop
$ python3.1 -mtimeit -s'import xx; x="aaa12333bb445bb54b5b52"' 'x.translate(xx.DD)'
10000 loops, best of 3: 24.3 usec per loop
...这表明性能优势消失了,对于这种“删除”任务,变成了性能下降。