有效检查字符串是否包含 python 中的数字
Efficiently check if string contains a digit in python
我有大量 (GB) 的文本要逐句处理。
在每个句子中,我都要对数字执行代价高昂的操作,因此我检查该句子是否至少包含一位数字。
我使用不同的方式完成了这项检查,并使用 timeit
.
测量了这些解决方案
s = 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz' # example
any(c.isdigit() for c in s)
3.61 微秒
re.search('\d', s)
402 纳秒
d = re.compile('\d')
d.search(s)
126 纳秒
'0' in s or '1' in s or '2' in s or '3' in s or '4' in s or '5' in s or '6' in s or '7' in s or '8' in s or '9' in s
60ns
最后一种方法是最快的,但它很丑,而且可能比可能的方法慢 10 倍。
当然我可以用 cython 重写它,但这似乎有点过分了。
是否有更好的纯python解决方案?特别是,我想知道为什么您可以将 str.startswith()
和 str.endswith()
与元组参数一起使用,但似乎无法使用 in
运算符。
实际性能可能因您的平台和 python 版本而异,但在我的设置中 (python 3.9.5 / Ubuntu),结果是 re.match
明显快于 re.search
,并且优于长 in
系列版本。此外,使用 [0-9]
而不是 \d
编译正则表达式提供了一点改进。
import re
from timeit import timeit
n = 10_000_000
s = 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz'
# reference
timeit(lambda: '0' in s or '1' in s or '2' in s or '3' in s or '4' in s or '5' in s or '6' in s or '7' in s or '8' in s or '9' in s, number=n)
# 2.1005349759998353
# re.search with \d, slower
re.compile('\d')
timeit(lambda: d.search(s), number=n)
# 2.9816031390000717
# re.search with [0-9], better but still slower then reference
d = re.compile('[0-9]')
timeit(lambda: d.search(s), number=n)
# 2.640713582999524
# re.match with [0-9], faster than reference
d = re.compile('[0-9]')
timeit(lambda: d.match(s), number=n)
# 1.5671786130005785
所以,在我的机器上,使用 re.match
和编译的 [0-9]
模式比长 or ... in
链接快大约 25% .而且看起来也更好。
我有大量 (GB) 的文本要逐句处理。
在每个句子中,我都要对数字执行代价高昂的操作,因此我检查该句子是否至少包含一位数字。
我使用不同的方式完成了这项检查,并使用 timeit
.
s = 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz' # example
any(c.isdigit() for c in s)
3.61 微秒re.search('\d', s)
402 纳秒d = re.compile('\d')
d.search(s)
126 纳秒'0' in s or '1' in s or '2' in s or '3' in s or '4' in s or '5' in s or '6' in s or '7' in s or '8' in s or '9' in s
60ns
最后一种方法是最快的,但它很丑,而且可能比可能的方法慢 10 倍。
当然我可以用 cython 重写它,但这似乎有点过分了。
是否有更好的纯python解决方案?特别是,我想知道为什么您可以将 str.startswith()
和 str.endswith()
与元组参数一起使用,但似乎无法使用 in
运算符。
实际性能可能因您的平台和 python 版本而异,但在我的设置中 (python 3.9.5 / Ubuntu),结果是 re.match
明显快于 re.search
,并且优于长 in
系列版本。此外,使用 [0-9]
而不是 \d
编译正则表达式提供了一点改进。
import re
from timeit import timeit
n = 10_000_000
s = 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz'
# reference
timeit(lambda: '0' in s or '1' in s or '2' in s or '3' in s or '4' in s or '5' in s or '6' in s or '7' in s or '8' in s or '9' in s, number=n)
# 2.1005349759998353
# re.search with \d, slower
re.compile('\d')
timeit(lambda: d.search(s), number=n)
# 2.9816031390000717
# re.search with [0-9], better but still slower then reference
d = re.compile('[0-9]')
timeit(lambda: d.search(s), number=n)
# 2.640713582999524
# re.match with [0-9], faster than reference
d = re.compile('[0-9]')
timeit(lambda: d.match(s), number=n)
# 1.5671786130005785
所以,在我的机器上,使用 re.match
和编译的 [0-9]
模式比长 or ... in
链接快大约 25% .而且看起来也更好。