2011-02-04 9 views
38

Dla pojedynczych wyszukiwań łańcuchowych, czy szybsze jest użycie str.find/rfind niż użycie polecenia re.match/search?Co to jest szybsza operacja, re.match/search lub str.find?

Oznacza to, że dla danego łańcucha, s, należy użyć:

if s.find('lookforme') > -1: 
    do something 

lub

if re.match('lookforme',s): 
    do something else 

?

+3

Dla jednorazowej, jestem dość pewny, że regex będzie wolniejszy, z powodu dodatkowego naddatku. –

+1

Powinieneś uważać, porównując te dwa, ponieważ mają one inną funkcjonalność. Znajdź przeszukuje cały ciąg, natomiast dopasowanie odpowiada tylko początkowi (tzn. Może wyjść wcześniej, w zależności od danych). Więc porównujesz tam jabłka i pomarańcze. –

Odpowiedz

91

Pytanie: który jest szybszy najlepiej odpowiedzieć, używając timeit.

from timeit import timeit 
import re 

def find(string, text): 
    if string.find(text) > -1: 
     pass 

def re_find(string, text): 
    if re.match(text, string): 
     pass 

def best_find(string, text): 
    if text in string: 
     pass 

print timeit("find(string, text)", "from __main__ import find; string='lookforme'; text='look'") 
print timeit("re_find(string, text)", "from __main__ import re_find; string='lookforme'; text='look'") 
print timeit("best_find(string, text)", "from __main__ import best_find; string='lookforme'; text='look'") 

Wyjście jest:

0.441393852234 
2.12302494049 
0.251421928406 

Więc nie tylko należy użyć operatora in, ponieważ jest łatwiejszy do odczytania, ale dlatego, że jest szybsza również.

+2

Mikro-optymalizacje w najlepszym razie do wyboru na podstawie czasu. Jednak +1 od czasu, kiedy podano najbardziej czytelny przypadek ... – ircmaxell

+5

Z pewnością odpowiedziałeś na pytanie właściwie, sukhbir. Uzgodniono, ale +1 dla czytelności i że udowodniono, że odpowiedź jest "pythonic". –

+4

Najwyraźniej prowadziłeś automatyczne jury, nazywając jeden "best_find" ;-) –

14

Użyj tego:

if 'lookforme' in s: 
    do something 

Regex muszą być kompilowane najpierw, co dodaje trochę nad głową. Normalne wyszukiwanie ciągów w Pythonie jest bardzo skuteczne.

Jeśli często przeszukujesz ten sam termin lub gdy robisz coś bardziej złożonego, to wyrażenie regularne staje się bardziej użyteczne.

+4

+1 Najpierw pythonic - wtedy, jeśli wydajność staje się problemem, zapoznaj się z różnymi implementacjami, aby sprawdzić, czy poprawiają wydajność. –

7

re.compile przyspiesza wyliczenia, jeśli szukasz tego samego w kółko. Ale właśnie dostałem ogromną szybkość, używając "w", aby wyłapać złe przypadki, zanim się dopasuję. Anegdota, wiem. ~ Ben

2

Miałem ten sam problem. Kiedyś Jupyter za% timeit sprawdzić:

import re 
sent = "a sentence for measuring a find function" 
sent_list = sent.split() 
print("x in sentence") 
%timeit "function" in sent 
print("x in token list") 
%timeit "function" in sent_list 

print("regex search") 
%timeit bool(re.match(".*function.*", sent)) 
print("compiled regex search") 
regex = re.compile(".*function.*") 
%timeit bool(regex.match(sent)) 

X w zdaniu 61,3 ns ± 3 ns na pętli (.. Średnia ± std dev z 7 serii, 10000000 pętli każda)

xw tokena liście 93.3 ns ± 1,26 ns każdej pętli (średnia ± Std dev., 7 serii, 10000000 pętli każda)

regex wyszukiwania 772 ns ± 8,42 ns, w każdej pętli (średnia ± Std dev., 7 serii, 1000000 pętle każda)

skompilowane wyszukiwanie regex 420 ns ± 7,68 ns na pętlę (średnia ± std. Dev z 7 serii, po 1000000 pętli)

Kompilacja jest szybka, ale prosta jest lepsza.