Python:从string中除去数字以外的字符
我如何删除string中除数字以外的所有字符?
在Python 2. *中,最快的方法是.translate
方法:
>>> x='aaa12333bb445bb54b5b52' >>> import string >>> all=string.maketrans('','') >>> nodigs=all.translate(all, string.digits) >>> x.translate(all, nodigs) '1233344554552' >>>
string.maketrans
创build一个转换表(一个长度为256的string),在这种情况下,它与''.join(chr(x) for x in range(256))
(只是更快; ''.join(chr(x) for x in range(256))
。 .translate
应用翻译表(这里是不相关的,因为all
本质都意味着同一性),并删除第二个参数中出现的字符 – 关键部分。
.translate
在Unicodestring(和Python 3中的string) .translate
工作方式有很大的不同 – 我希望指定哪些主要版本的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
方法值得认识和运用。 其他stream行的非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
这表明性能优势消失了,对于这种“删除”任务,并成为一个性能下降。
使用re.sub
,如下所示:
>>> import re >>> re.sub("\D", "", "aas30dsa20") '3020'
\D
匹配任何非数字字符,所以上面的代码基本上replace了空string的每个非数字字符。
或者你可以使用filter
,就像这样(在Python 2k中):
>>> filter(lambda x: x.isdigit(), "aas30dsa20") '3020'
由于在Python 3k中, filter
返回一个迭代器而不是一个list
,你可以使用下面的代码:
>>> ''.join(filter(lambda x: x.isdigit(), "aas30dsa20")) '3020'
s=''.join(i for i in s if i.isdigit())
另一个发电机变种
你可以使用filter:
filter(lambda x: x.isdigit(), "dasdasd2313dsa")
在python3.0你必须join这个(有点丑:( :()
''.join(filter(lambda x: x.isdigit(), "dasdasd2313dsa"))
沿着拜耳的答案:
''.join(i for i in s if i.isdigit())
x.translate(None, string.digits)
将从string中删除所有数字。 要删除字母并保留数字,请执行以下操作:
x.translate(None, string.letters)
你可以很容易地使用正则expression式
>>> import re >>> re.sub("\D","","£70,000") 70000
操作中提到他要保留小数位。 这可以通过re.sub方法(按照第二和恕我直言最好的答案)通过明确列出字符,以保持例如
>>> re.sub("[^0123456789\.]","","poo123.4and5fish") '123.45'
Python 3的快速版本:
# xx3.py from collections import defaultdict import string _NoneType = type(None) def keeper(keep): table = defaultdict(_NoneType) table.update({ord(c): c for c in keep}) return table digit_keeper = keeper(string.digits)
这是一个性能比较与正则expression式:
$ python3.3 -mtimeit -s'import xx3; x="aaa12333bb445bb54b5b52"' 'x.translate(xx3.digit_keeper)' 1000000 loops, best of 3: 1.02 usec per loop $ python3.3 -mtimeit -s'import re; r = re.compile(r"\D"); x="aaa12333bb445bb54b5b52"' 'r.sub("", x)' 100000 loops, best of 3: 3.43 usec per loop
所以比正则expression式要快三倍多。 它也比上面的class Del
更快,因为defaultdict
在C中执行所有查找,而不是(慢)Python。 这是在同一个系统上的版本,用于比较。
$ python3.3 -mtimeit -s'import xx; x="aaa12333bb445bb54b5b52"' 'x.translate(xx.DD)' 100000 loops, best of 3: 13.6 usec per loop
丑但是作品:
>>> s 'aaa12333bb445bb54b5b52' >>> a = ''.join(filter(lambda x : x.isdigit(), s)) >>> a '1233344554552' >>>
使用生成器expression式:
>>> s = "foo200bar" >>> new_s = "".join(i for i in s if i in "0123456789")