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

我有一个很好的工作snippit的代码,但我想知道如果有人有任何更好的build议,如何做到这一点:

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

你会怎么做?

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

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

另一种“pythonic”方法

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

但正则expression式更快。

以下是一些示例代码:

 $ 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 

看起来像正则expression式是迄今为止的胜利者。

就个人而言,我发现正则expression式与列表理解一样可读。 如果你只是这样做了几次,那么编译正则expression式可能会更大。 用你的代码和编码风格做什么?

我的解决scheme使用正则expression式更简单:

 import re re.sub("[^0-9^.]", "", data) 
 import string filter(lambda c: c in string.digits + '.', s) 

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

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

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

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

哦,这是我在这个testingstring上发现的最快的方法(比正则expression式要快得多),如果你这么做了很多次,并且愿意忍受构build几个字符表的开销。

 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秒,正则expression式b.py在4.3秒内运行。