2010-03-12 14 views
37

Ho una funzione di scegliere grumi da una lista di stringhe e di ritorno, un altro elenco:Come usare re partita oggetti in una comprensione lista

def filterPick(lines,regex): 
    result = [] 
    for l in lines: 
     match = re.search(regex,l) 
     if match: 
      result += [match.group(1)] 
    return result 

C'è un modo per riformulare questo come un elenco comprensione? Ovviamente è abbastanza chiaro com'è; solo curioso.


Grazie a coloro che hanno contribuito, menzione speciale per @Alex. Ecco una versione condensata di ciò che ho finito con; il metodo di espressione regolare corrispondenza viene passata a filterPick come parametro "pre-issata":

import re 

def filterPick(list,filter): 
    return [ (l, m.group(1)) for l in list for m in (filter(l),) if m] 

theList = ["foo", "bar", "baz", "qurx", "bother"] 
searchRegex = re.compile('(a|r$)').search 
x = filterPick(theList,searchRegex) 

>> [('bar', 'a'), ('baz', 'a'), ('bother', 'r')] 

risposta

66
[m.group(1) for l in lines for m in [regex.search(l)] if m] 

Il "trucco" è la parte for m in [regex.search(l)] - è così che si "assegna" un valore che è necessario utilizzare più di una volta, all'interno di una lista di comprensione - aggiungi solo una clausola di questo tipo, in cui l'oggetto "scorre" su una lista di singoli elementi contenente l'unico valore che vuoi "assegnare" ad esso. Alcuni considerano questo stilisticamente discutibile, ma a volte lo trovo pratico.

+1

Alex, mi piace; grazie e +1. Ho un po 'di sollievo abbastanza pesante da fare con questo codice - dovrei preoccuparmi del sovraccarico extra di installazione e abbattimento del "finto iteratore"? A proposito, sottoscrivo la dottrina di "ottimizzare più tardi". –

+1

@Brent, il "faux iterator" dovrebbe essere trascurabile rispetto alla chiamata di ricerca; un'ottimizzazione minore è usare '(regex.search (l),)' invece di '[regex.search (l)]' (che trovo più leggibile ma è minuziosamente lento - pensavo che non si potesse in fretta perché in effetti stavi chiamando la funzione 're.search' dal modulo piuttosto che il metodo di re object.Tirare il comando' regex.search' come metodo vincolato al di fuori di listcomp è un'altra ottimizzazione minore ma utile, btw –

+0

as Appena ho visto la tua risposta ho capito che usare re.search non era il modo migliore per andare. Potresti chiarire per me come potresti "[tirare] regex.search come metodo vincolato al di fuori della listcomp"? la tua pazienza con un listcomp e Python noob –

9
return [m.group(1) for m in (re.search(regex, l) for l in lines) if m] 
7

Potrebbe essere accorciato un po '

def filterPick(lines, regex): 
    matches = map(re.compile(regex).match, lines) 
    return [m.group(1) for m in matches if m] 

si potrebbe mettere tutto in una sola riga, ma ciò significherebbe che avrebbe dovuto corrispondere ogni linea due volte, che sarebbe un po' meno efficiente.

+2

Nah, non c'è bisogno di abbinare ogni riga due volte, vedere la mia risposta. –

+0

In effetti, la tua risposta è molto più pulita, +1 da me :) – Wolph

-13
>>> "a" in "a visit to the dentist" 
True 
>>> "a" not in "a visit to the dentist" 
False 

che funziona anche con una query di ricerca siete a caccia giù in una lista

`P = 'a', 'b', 'c'

'b' in P` restituisce true

+1

Come risponde la domanda? –

+0

Queste domande possono presentare un modo migliore per controllare gli input in una lista rispetto a re, ma tra l'altro non funzionano se non vuoi ottenere i risultati grep. U può sempre fare un semplice ciclo attorno all'output. Non c'è molta differenza per farlo manualmente rispetto a usare una funzione che fa lo stesso ... – erm3nda

Problemi correlati