Próbuję tworzyć warianty ciągów, stosując opcjonalnie substytucje.Kombinatoryczny produkt substytucji regex
Na przykład, jednym schematem zastępowania jest usunięcie dowolnej sekwencji pustych znaków. Zamiast zastąpienie wszystkich zjawisk jak
>>> re.sub(r'\s+', '', 'a b c')
'abc'
- muszę, natomiast dwa warianty być wytwarzane na każdym wystąpieniu, że podstawienie prowadzi się w jednym z wariantów, ale nie w drugiej. dla struny 'a b c'
chcę mieć warianty
['a b c', 'a bc', 'ab c', 'abc']
tj. krzyżowy produkt wszystkich decyzji binarnych (wynik oczywiście zawiera oryginalny ciąg znaków).
W tym przypadku, warianty mogą być wytwarzane re.finditer
i itertools.product
:
def vary(target, pattern, subst):
occurrences = [m.span() for m in pattern.finditer(target)]
for path in itertools.product((True, False), repeat=len(occurrences)):
variant = ''
anchor = 0
for (start, end), apply_this in zip(occurrences, path):
if apply_this:
variant += target[anchor:start] + subst
anchor = end
variant += target[anchor:]
yield variant
To daje pożądany wynik dla powyższego przykładu:
>>> list(vary('a b c', re.compile(r'\s+'), ''))
['abc', 'ab c', 'a bc', 'a b c']
Jednakże rozwiązanie to działa tylko na stałe -string zastępstwa. zaawansowane funkcje z re.sub
jak odniesień grupy nie można zrobić tak, jak w poniższym przykładzie do wstawiania spacji po sekwencji cyfr wewnątrz słowem:
re.sub(r'\B(\d+)\B'), r'\1 ', 'abc123def')
jaki sposób podejście zostać rozszerzony lub zmieniony zaakceptować dowolny poprawny argument do re. (bez zapisywania analizatora składni do interpretowania odniesień do grupy)?
Dzięki, to bardzo dobra wskazówka! Ograniczenia dla argumentu, który można wywołać, można łatwo usunąć, nadając mu ogólny charakter: w pętli wewnętrznej zamień '... + match.expand (subst)' na '... + subst (dopasowanie)'. Jeśli argument nie jest uruchamiany, po prostu zapisz funkcję (na początku kodu): 'if not callla (subst): static_subst = subst; subst = lambda m: m.expand (static_subst) ' – lenz