2014-02-13 138 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'] 
相關問題