我可以更快地制作这个(Python)正则表达式吗?

时间:2014-02-13 15:07:46

标签: python regex

我正在尝试编写一个匹配形式为##-##的字符串的正则表达式(其中#对应于任何数字),但需要注意的是第二对数字不能为“00”。该表达式应该与re.search一起使用,并且应该捕获匹配模式的第一次出现。

这是我得到的(有效):

the_regex = re.compile("(\d\d-(?:0[123456789]|[123456789]\d))")

我不喜欢分支或长字符组。任何人都可以建议一个更好的(更清晰,或可选,更有效)正则表达式吗?

(是的,这是微观优化,我已经听从了Knuth的正确警告。)

3 个答案:

答案 0 :(得分:4)

使用字符范围可以轻松解决长字符组:

r"(\d\d-(?:0[1-9]|[1-9]\d))"

但你无法避开这里的分支。

答案 1 :(得分:3)

the_regex = re.compile("(\d\d-(?:0[1-9]|[1-9]\d))")



l = re.findall(the_regex, '11-01 11-99 10-29 01-99 00-00 11-00')
print l

所示:

['11-01', '11-99', '10-29', '01-99']

如果你使用re.finditer,它会返回一个生成器,这对你来说可能更好:

it = re.finditer(the_regex, '11-01 11-99 10-29 01-99 00-00 11-00')
print type(it)
print list(i.group(0) for i in it)

显示了这一点:

<type 'callable-iterator'>
['11-01', '11-99', '10-29', '01-99']

答案 2 :(得分:1)

另一种可能性......我不确定这是否可行,但似乎......它使用了前瞻断言:

r2 = re.compile(r"(\d\d-(?!00)\d\d)")
l = re.findall(r2, 'On 02-14 I went looking for 12-00 and 14-245')
print l
['02-14', '14-24']

然而......它似乎没有更快(与上述解决方案相比)。事实上,最初的解决方案是最快的:

# Martijn/Aaron's solution
In [20]: %timeit l = re.findall(the_regex2, '11-01 11-99 10-29 01-99 00-00 11-00')
100000 loops, best of 3: 3.55 µs per loop

# Above version
In [21]: %timeit l = re.findall(r2, '11-01 11-99 10-29 01-99 00-00 11-00')
100000 loops, best of 3: 3.49 µs per loop

#Original post's version.
In [25]: the_regex = re.compile("(\d\d-(?:0[123456789]|[123456789]\d))")
In [26]: %timeit l = re.findall(the_regex, '11-01 11-99 10-29 01-99 00-00 11-00')    
100000 loops, best of 3: 3.41 µs per loop