从Python中的字符串中删除所有非数字字符(“。”除外)

时间:2009-06-03 23:12:00

标签: python

我有一个非常好的工作代码,但我想知道是否有人对如何做到这一点有更好的建议:

val = ''.join([c for c in val if c in '1234567890.'])

你会做什么?

5 个答案:

答案 0 :(得分:111)

您可以使用正则表达式(使用re模块)来完成同样的事情。下面的示例匹配[^\d.](任何不是十进制数字或句点的字符)的运行,并用空字符串替换它们。请注意,如果使用UNICODE标志编译模式,则生成的字符串仍可包含non-ASCII numbers。此外,删除“非数字”字符后的结果不一定是有效数字。

>>> import re
>>> non_decimal = re.compile(r'[^\d.]+')
>>> non_decimal.sub('', '12.34fe4e')
'12.344'

答案 1 :(得分:17)

另一种'pythonic'方法

filter( lambda x: x in '0123456789.', s )

但正则表达式更快。<​​/ p>

答案 2 :(得分:13)

以下是一些示例代码:

$ cat a.py
a = '27893jkasnf8u2qrtq2ntkjh8934yt8.298222rwagasjkijw'
for i in xrange(1000000):
    ''.join([c for c in a if c in '1234567890.'])

$ cat b.py
import re

non_decimal = re.compile(r'[^\d.]+')

a = '27893jkasnf8u2qrtq2ntkjh8934yt8.298222rwagasjkijw'
for i in xrange(1000000):
    non_decimal.sub('', a)

$ cat c.py
a = '27893jkasnf8u2qrtq2ntkjh8934yt8.298222rwagasjkijw'
for i in xrange(1000000):
    ''.join([c for c in a if c.isdigit() or c == '.'])

$ cat d.py
a = '27893jkasnf8u2qrtq2ntkjh8934yt8.298222rwagasjkijw'
for i in xrange(1000000):
    b = []
    for c in a:
        if c.isdigit() or c == '.': continue
        b.append(c)

    ''.join(b)

时间结果:


$ time python a.py
real    0m24.735s
user    0m21.049s
sys     0m0.456s

$ time python b.py
real    0m10.775s
user    0m9.817s
sys     0m0.236s

$ time python c.py
real    0m38.255s
user    0m32.718s
sys     0m0.724s

$ time python d.py
real    0m46.040s
user    0m41.515s
sys     0m0.832s

到目前为止看起来正则表达式是胜利者。

就个人而言,我发现正则表达式与列表理解一样可读。如果你只做了几次,那么你可能会在编译正则表达式时受到更大的打击。用你的代码和编码风格做点什么。

答案 3 :(得分:8)

一个简单的解决方案是使用常规的经历

import re 
re.sub("[^0-9^.]", "", data)

答案 4 :(得分:2)

如果字符集较大,则使用以下设置可能会更快。实际上,这比a.py慢一点。

dec = set('1234567890.')

a = '27893jkasnf8u2qrtq2ntkjh8934yt8.298222rwagasjkijw'
for i in xrange(1000000):
    ''.join(ch for ch in a if ch in dec)

至少在我的系统上,你可以通过在a.py中使用生成器表达式而不是列表理解来节省一点时间(如果你的字符串足够长,则可以节省内存):

a = '27893jkasnf8u2qrtq2ntkjh8934yt8.298222rwagasjkijw'
for i in xrange(1000000):
    ''.join(c for c in a if c in '1234567890.')

哦,这是我迄今为止在这个测试字符串上找到的最快的方法(比正则表达式快得多)如果你这么做很多次,并且愿意忍受构建几个字符的开销表。

chrs = ''.join(chr(i) for i in xrange(256))
deletable = ''.join(ch for ch in chrs if ch not in '1234567890.')

a = '27893jkasnf8u2qrtq2ntkjh8934yt8.298222rwagasjkijw'
for i in xrange(1000000):
    a.translate(chrs, deletable)

在我的系统上,运行时间约为1.0秒,正则表达式b.py在~4.3秒内运行。