2010-03-12 3 views
37

Tengo una función para escoger trozos de una lista de cadenas y devolverlos como otra lista:Cómo utilizar objetos de los partidos re en una lista por comprensión

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

¿Hay una manera de reformular esto como una lista ¿comprensión? Obviamente está bastante claro como está; Sólo curioso.


Gracias a los que contribuyeron, mención especial para @Alex. Aquí hay una versión condensada de lo que terminé; el método de coincidencia de expresiones regulares se pasa a filterPick como un parámetro de "pre-izado":

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

Respuesta

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

El "truco" es la parte for m in [regex.search(l)] - así es como se "asigna" un valor que es necesario utilizar más de una vez, dentro de una lista de comprensión, agregue solo una cláusula, donde el objeto "itera" sobre una lista de un solo elemento que contiene el único valor que quiere "asignarle". Algunos lo consideran estilísticamente dudoso, pero a veces me resulta práctico.

+1

Alex, me gusta eso; gracias y +1. Tengo que lidiar con este código bastante pesado, ¿debería preocuparme por la sobrecarga adicional de configurar y demoler el "iterador falso"? Por cierto me suscribo a la doctrina de "optimizar más tarde". –

+1

@Brent, el "iterador falso" debe ser despreciable con la búsqueda; una optimización menor es usar '(regex.search (l),)' en lugar de '[regex.search (l)]' (que me parece más fácil de leer pero es mucho más lenta, pensé que no podrías ser de prisa, ya que en realidad llamaba a la función 're.search' del módulo en lugar del método del objeto re. Tirar' regex.search' como un método vinculado fuera de listcomp es otra optimización menor pero útil, por cierto, –

+0

como Tan pronto como vi tu respuesta, me di cuenta de que el uso de re.search no era la mejor manera de hacerlo. ¿Podrías aclararme cómo harías "[tire de] regex.search como un método vinculado fuera de la listacomp"? Realmente aprecio tu paciencia con un listcomp y un novato de Python. –

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

Podría ser acortado un poco

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

se puede poner todo en una sola línea, pero eso significaría que tendría que coincidir con cada línea doble de lo que sería un poco menos eficiente.

+2

Nah, no hay necesidad de hacer coincidir cada línea dos veces, ver mi respuesta. –

+0

De hecho, su respuesta es mucho más clara, +1 de mí :) – Wolph

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

Eso también funciona con una consulta de búsqueda que estés cazando en una lista

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

'b' en P` devuelve verdadero

+1

¿Cómo responde eso la pregunta? –

+0

Estas preguntas pueden presentar una mejor manera de verificar las entradas en una lista que re, pero por cierto no funcionan si no quieres grep resultados. U siempre puede hacer un bucle simple para la salida de re. No hay mucha diferencia para hacerlo manualmente que usar una función que haga lo mismo ... – erm3nda

Cuestiones relacionadas