从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秒内运行。