如何从字符串中删除除数字之外的所有字符?
在 Python 2.* 中,迄今为止最快的方法是以下.translate方法:
.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本质上意味着身份)并删除第二个参数中存在的字符 - 关键部分。
string.maketrans
''.join(chr(x) for x in range(256))
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 方法…:
translate
$ 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您要删除的内容。这是删除“除了”几个字符之外的所有内容的一种方便的表达方式:
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 中,我们有......:
'1233344554552'
$ 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
…这表明性能优势消失了,对于这种“删除”任务,变成了性能下降。