2014-02-13 76 views
3

我想写一个匹配##-##(其中#对应于任何数字)形式的字符串的正则表达式,并注意第二对数字不能为“00”。该表达式应该可以与re.search一起使用,并且应该捕获匹配模式的第一个匹配项。我可以使这个(Python)正则表达式更快吗?

下面是我得到了什么(工作):

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

我不是野生的分支或长的字符组。任何人都可以提出更好的(更清晰的,或者更有效的)正则表达式吗?

(是的,这是一个微型的优化,我已经从克努特听取正确的警告。)

+1

它应该匹配时,如果字符串包含类似:'123-123'? (您目前的表达式(以及迄今为止的所有答案)不会强制执行边界条件,并且将匹配:'123-123'内的'23-12'。) – ridgerunner

+0

@ridgerunner好点,但在这种情况下,它匹配的字符串保证不会有这种情况。 – dcrosta

回答

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 
+0

或're.compile(“(\ d \ d - (?:(?!00)\ d \ d))”)'将OPT中的'(?:)'保留。 – WKPlus

+0

我不认为这会伤害任何东西,但我不认为这是必要的......原来是这样做的,因为'|'必须在一个组中,并且如果您不将其标记为非捕捉它成为一个单独的组。 '\ d \ d'不在这一个单独的组中,而'(!!00)'这个术语已经是非捕获的,所以它实际上并没有添加任何东西,我想。 –

+0

在我的测试用例中(我应该已经展示了一些示例数据),这被证明是最快的(不出所料,这个数值相当小)。 – dcrosta

4

长字符组迎刃而解使用一个字符范围来代替:

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

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

+0

三分钟打我。 –

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'] 
相关问题