2013-02-11 10 views
7

Próbuję zlokalizować wszystkie pozycje indeksu łańcucha na liście słów i chcę wartości zwrócone jako listy. Chciałbym znaleźć ciąg znaków, jeśli jest on samodzielny, lub jeśli jest poprzedzony lub następuje interpunkcją, ale nie jeśli jest podłańcuchem większego słowa.Jak korzystać z wyrażenia regularnego w zrozumieniu listy w Pythonie?

Poniższy kod przechwytuje tylko "krowa" i pomija zarówno "test, krowa", jak i "krowa".

myList = ['test;cow', 'one', 'two', 'three', 'cow.', 'cow', 'acow'] 
myString = 'cow' 
indices = [i for i, x in enumerate(myList) if x == myString] 
print indices 
>> 5 

Próbowałem zmiany kodu, aby użyć wyrażenia regularnego:

import re 
myList = ['test;cow', 'one', 'two', 'three', 'cow.', 'cow', 'acow'] 
myString = 'cow' 
indices = [i for i, x in enumerate(myList) if x == re.match('\W*myString\W*', myList)] 
print indices 

Ale to daje błąd: ciąg spodziewane lub bufor

Jeśli ktoś wie co robię źle I Byłbym bardzo szczęśliwy słysząc. Mam wrażenie, że ma to coś wspólnego z tym, że próbuję użyć wyrażenia regularnego tam, gdzie oczekuje się ciągu znaków. Czy istnieje rozwiązanie?

Wyjście szukam powinien brzmieć:

>> [0, 4, 5] 

Dzięki

Odpowiedz

14

Nie trzeba przypisać wynik match z powrotem do x. Twój mecz powinien być na x zamiast na list.

Należy również użyć re.search zamiast re.match, ponieważ wzór regex '\W*myString\W*' nie będzie zgodny z pierwszym elementem. To dlatego, że test; nie jest dopasowany przez \W*. W rzeczywistości wystarczy przetestować pod kątem natychmiastowego następowania i poprzedzania znaku, a nie całego ciągu znaków.

Tak, można raczej użyć word boundaries wokół napisu:

pattern = r'\b' + re.escape(myString) + r'\b' 
indices = [i for i, x in enumerate(myList) if re.search(pattern, x)] 
4

Istnieje kilka problemów z kodem. Najpierw należy dopasować wyrażenie do elementu listy (x), a nie do całej listy (myList). Po drugie, aby wstawić zmienną do wyrażenia, musisz użyć + (łączenia ciągów). I wreszcie, należy użyć surowych literałów (r'\W), aby prawidłowo Interpet ukośniki w expr:

import re 
myList = ['test;cow', 'one', 'two', 'three', 'cow.', 'cow', 'acow'] 
myString = 'cow' 
indices = [i for i, x in enumerate(myList) if re.match(r'\W*' + myString + r'\W*', x)] 
print indices 

Jeśli istnieją szanse, że myString zawiera znaki specjalne wyrażeń regularnych (jak ukośnikiem lub kropką) Trzeba także stosować re.escape do niego:

regex = r'\W*' + re.escape(myString) + r'\W*' 
indices = [i for i, x in enumerate(myList) if re.match(regex, x)] 

Jak zauważył w komentarzach, następujące może być lepszym rozwiązaniem:

regex = r'\b' + re.escape(myString) + r'\b' 
indices = [i for i, x in enumerate(myList) if re.search(regex, x)] 
+0

może dodać 're.escape' też? –

+0

@MartijnPieters: jasne, dodane. – georg

+0

To nie pasuje do pierwszego elementu, który OP chce dopasować. –

Powiązane problemy