2010-09-21 15 views
9

używam następujący kod:różne zachowanie między re.finditer i re.findall

CARRIS_REGEX=r'<th>(\d+)</th><th>([\s\w\.\-]+)</th><th>(\d+:\d+)</th><th>(\d+m)</th>' 
pattern = re.compile(CARRIS_REGEX, re.UNICODE) 
matches = pattern.finditer(mailbody) 
findall = pattern.findall(mailbody) 

Ale finditer i findall napotykają różne rzeczy. Findall rzeczywiście znajduje wszystkie dopasowania w danym ciągu. Ale finditer znajduje tylko pierwszą, zwracając iterator z tylko jednym elementem.

Jak mogę sprawić, aby Finditer i Findall zachowywały się w ten sam sposób?

Dzięki

+0

W jaki sposób korzystasz z iteratora lub określasz, ile wyników zwróci? – geoffspear

+0

używanie meczu w meczach i ich drukowanie. dzięki. – simao

+0

Czy możesz opublikować treść wiadomości e-mail, której dotyczy ten problem? – kindall

Odpowiedz

20

Nie mogę tego tutaj powtórzyć. Wypróbowałem go zarówno w Pythonie 2.7, jak i 3.1.

Jedna różnica między finditer i findall polega na tym, że pierwsza zwraca obiekty dopasowania do wyrażenia regularnego, podczas gdy druga zwraca krotkę dopasowanych grup przechwytywania (lub całe dopasowanie, jeśli nie ma grup przechwytywania).

So

import re 
CARRIS_REGEX=r'<th>(\d+)</th><th>([\s\w\.\-]+)</th><th>(\d+:\d+)</th><th>(\d+m)</th>' 
pattern = re.compile(CARRIS_REGEX, re.UNICODE) 
mailbody = open("test.txt").read() 
for match in pattern.finditer(mailbody): 
    print(match) 
print() 
for match in pattern.findall(mailbody): 
    print(match) 

drukuje

<_sre.SRE_Match object at 0x00A63758> 
<_sre.SRE_Match object at 0x00A63F98> 
<_sre.SRE_Match object at 0x00A63758> 
<_sre.SRE_Match object at 0x00A63F98> 
<_sre.SRE_Match object at 0x00A63758> 
<_sre.SRE_Match object at 0x00A63F98> 
<_sre.SRE_Match object at 0x00A63758> 
<_sre.SRE_Match object at 0x00A63F98> 

('790', 'PR. REAL', '21:06', '04m') 
('758', 'PORTAS BENFICA', '21:10', '09m') 
('790', 'PR. REAL', '21:14', '13m') 
('758', 'PORTAS BENFICA', '21:21', '19m') 
('790', 'PR. REAL', '21:29', '28m') 
('758', 'PORTAS BENFICA', '21:38', '36m') 
('758', 'SETE RIOS', '21:49', '47m') 
('758', 'SETE RIOS', '22:09', '68m') 

Jeśli chcesz tego samego wyjścia z finditer jak dostajesz od findall, trzeba

for match in pattern.finditer(mailbody): 
    print(tuple(match.groups())) 
+0

Nie wiem, dlaczego to nie działało. Odinstaluj Pythona 2.5 i zaktualizowałem go do wersji 2.6, a teraz działa: | – simao

+0

@JeromeJ: Dzięki za twój (teraz usunięty) komentarz - masz absolutną rację. –

4

Nie można uczynić je zachowują się w ten sam sposób, ponieważ są one różne. Jeśli naprawdę chcesz stworzyć listę wyników z finditer, następnie można użyć wyrażeń listowych:

>>> [match for match in pattern.finditer(mailbody)] 
[...] 

Generalnie, należy użyć for pętlę aby uzyskać dostęp do wyników zwracanych przez re.finditer:

>>> for match in pattern.finditer(mailbody): 
...  ... 
+0

Tak, wiem o tym. Problem polega na tym, że nie znajdują takich samych dopasowań. findall znajduje wszystkie dopasowania w ciągu znaków. finditer znajduje tylko pierwszą i tak, użyłem pętli for in, aby przetrawić wszystkie elementy iteratora. – simao

+6

'[Dopasuj do dopasowania we wzorcu.finditer (poczta pocztowa)]' jest po prostu wolniejszym i mniej czytelnym sposobem wypowiadania 'list (pattern.finditer (mailbody))' – aaronasterling

+0

Dzięki @ArronMcSmooth, dobry punkt. –

4

re. findall (pattern.string)

findall() zwraca wszystkie nie pokrywających mecze wzór w ciąg jako lista ciągów.

re.finditer()

finditer() zwraca obiektem wywoływalnym.

W obu funkcjach ciąg jest skanowany od lewej do prawej, a wyniki są zwracane w kolejności, w jakiej zostały znalezione.

Powiązane problemy