2014-02-13 5 views
3

Я пытаюсь написать регулярное выражение, которое соответствует строке формы ##-## (где # соответствует любой цифре), с оговоркой, что вторая пара цифр не может быть «00». Выражение должно использоваться с re.search и должно фиксировать первое вхождение шаблона соответствия.Могу ли я сделать это (Python) регулярное выражение быстрее?

Вот что у меня есть (который работает):

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

Я не дикий о филиале или длинных групп символов. Может ли кто-нибудь предложить лучшее (более понятное или необязательно более эффективное) регулярное выражение?

(Да, это микро-оптимизации, и я внял соответствующие предупреждения от Кнута.)

+1

Должно ли оно соответствовать, когда строка содержит что-то вроде: '123-123'? (Ваше текущее выражение (и все ответы до сих пор) не обеспечивает никаких граничных условий и будет соответствовать: '23-12' внутри:' 123-123'.) – ridgerunner

+0

@ridgerunner хорошая точка, но в этом случае строки, соответствующие совпадению гарантированно не иметь этого случая. – dcrosta

ответ

1

Еще одна возможность ... я не был su повторно, если это будет работать, но это, кажется .... он использует LOOKAHEAD утверждения:

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)) ")' сохранить '(? :)' в OP. – 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'] 
Смежные вопросы