2010-09-21 14 views
9

Sto usando il seguente codice:comportamenti differenti tra re.finditer e 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) 

Ma finditer e findall stanno trovando cose diverse. Findall in effetti trova tutte le corrispondenze nella stringa data. Ma finditer trova solo il primo, restituendo un iteratore con un solo elemento.

Come faccio a fare finder e findall si comportano allo stesso modo?

Grazie

+0

Come si utilizza l'iteratore o determinare il numero di risultati restituiti? – geoffspear

+0

utilizzando una corrispondenza per le partite e stampandole. Grazie. – simao

+0

Puoi pubblicare un messaggio di posta elettronica con il quale stai riscontrando questo problema? – kindall

risposta

20

Non posso riprodurre questo qui. L'ho provato con Python 2.7 e 3.1.

Una differenza tra finditer e findall è che il primo oggetti rendimenti regex partita mentre l'altro restituisce una tupla dei gruppi di cattura abbinati (o l'intera partita se non ci sono gruppi di cattura).

Così

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) 

stampe

<_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') 

Se si desidera che la stessa uscita da finditer come si sta ottenendo da findall, è necessario

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

Non so perché non funzionava. Ho disinstallato python 2.5 e aggiornato a 2.6 e ora funziona: | – simao

+0

@JeromeJ: Grazie per il tuo commento (ora rimosso) - avevi assolutamente ragione. –

4

Non è possibile farli comportano allo stesso modo, perché sono diversi. Se davvero si vuole creare un elenco di risultati di finditer, allora si potrebbe utilizzare una lista di comprensione:

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

In generale, utilizzare un ciclo for per accedere alle partite restituiti da re.finditer:

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

Sì, lo so. Il problema è che non trovano le stesse corrispondenze. findall trova tutte le corrispondenze nella stringa. finditer trova solo il primo e sì ho usato un ciclo for in per attraversare tutti gli elementi nell'iteratore. – simao

+6

'[partita per partita in pattern.finditer (Corpo Email)]' è solo un modo più lento e meno leggibile di dire 'lista (pattern.finditer (Corpo Email))' – aaronasterling

+0

Grazie @ArronMcSmooth, buon punto. –

4

re. findall (pattern.string)

findall() restituisce tutte le partite che non si sovrappongono su modello in stringa come una lista di stringhe.

re.finditer()

finditer() restituisce oggetto invocabile.

In entrambe le funzioni, la stringa viene scansionata da sinistra a destra e le partite vengono restituite nell'ordine trovato.

Problemi correlati