La prima cosa che viene in mente sta spingendo l'anello al lato C utilizzando un generatore di espressione:
def matches_pattern(s, patterns):
return any(p.match(s) for p in patterns)
Probabilmente non lo fai anche bisogno di una funzione separata per quello.
Un'altra cosa che dovresti provare è creare un regex singolo, composito usando l'operatore di alternanza |
, in modo che il motore abbia la possibilità di ottimizzarlo per te. È inoltre possibile creare la regex dinamicamente da un elenco di modelli di stringa, se ciò è necessario:
def matches_pattern(s, patterns):
return re.match('|'.join('(?:%s)' % p for p in patterns), s)
Naturalmente è necessario avere le espressioni regolari in forma di stringa per questo al lavoro. Basta profilare entrambi e verificare quale sia più veloce :)
Si potrebbe anche voler dare un'occhiata a general tip for debugging regular expressions in Python. Questo può anche aiutare a trovare opportunità di ottimizzazione.
UPDATE: ero curioso e ho scritto un po 'di riferimento:
import timeit
setup = """
import re
patterns = [".*abc", "123.*", "ab.*", "foo.*bar", "11010.*", "1[^o]*"]*10
strings = ["asdabc", "123awd2", "abasdae23", "fooasdabar", "111", "11010100101", "xxxx", "eeeeee", "dddddddddddddd", "ffffff"]*10
compiled_patterns = list(map(re.compile, patterns))
def matches_pattern(str, patterns):
for pattern in patterns:
if pattern.match(str):
return True
return False
def test0():
for s in strings:
matches_pattern(s, compiled_patterns)
def test1():
for s in strings:
any(p.match(s) for p in compiled_patterns)
def test2():
for s in strings:
re.match('|'.join('(?:%s)' % p for p in patterns), s)
def test3():
r = re.compile('|'.join('(?:%s)' % p for p in patterns))
for s in strings:
r.match(s)
"""
import sys
print(timeit.timeit("test0()", setup=setup, number=1000))
print(timeit.timeit("test1()", setup=setup, number=1000))
print(timeit.timeit("test2()", setup=setup, number=1000))
print(timeit.timeit("test3()", setup=setup, number=1000))
L'uscita sulla mia macchina:
1.4120500087738037
1.662621021270752
4.729579925537109
0.1489570140838623
Quindi any
non sembra essere più veloce di quanto il tuo approccio originale . Costruire una regex anche dinamicamente non è molto veloce. Ma se riesci a creare un regex in anticipo e ad usarlo più volte, ciò potrebbe migliorare le prestazioni. Puoi anche adattare questo benchmark per testare altre opzioni :)
'' | '.join (patterns) 'non è sicuro. Regex è un linguaggio complesso. Tu vuoi racchiudere ogni termine in '(?: ...)' prima di essere al sicuro. –
@Karl: Verissimo, grazie per avermelo fatto notare. Non è ancora completamente sicuro, anche se ci sono back-reference coinvolti, penso. Questo deve essere considerato caso per caso. –
Grazie mille. Proverò a costruire la regex in anticipo. Inoltre non posso credere di aver dimenticato "any". – puffenstuff