Cómo utilizar re coincidencia de objetos en una lista de comprensión

Tengo una función para recoger los bultos de una lista de cadenas y se les devolverá como otra lista:

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 de comprensión? Obviamente, es bastante claro como es; sólo por curiosidad.


Gracias a aquellos que han contribuido, mención especial para @Alex. He aquí una versión resumida de lo que terminó con la expresión regular coincide método se pasa filterPick como un «pre-izada» parámetro:

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

5 Kommentare

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

    El «truco» es el for m in [regex.search(l)] parte-que es la manera de asignar un valor que usted necesita usar más de una vez, dentro de una comprensión de lista — acaba de añadir una cláusula de este tipo, donde el objeto «itera» a través de una sola lista de elementos que contiene el valor que desea asignar a la misma. Algunos consideran que este estilísticamente dudosa, pero me resulta práctico a veces.

    • Alex, me gusta, gracias y +1. Tengo bastante trabajo pesado a hacer con este código debería preocuparme por la sobrecarga adicional de ajuste-para arriba y abajo rasgando la «imitación de iterador»? Por CIERTO me suscribo a la doctrina de «optimizar más tarde».
    • la «imitación de iterador» debería ser insignificante respecto de la búsqueda de la llamada; una menor de optimización es el uso de (regex.search(l),) en lugar de [regex.search(l)] (que me parece más legible, pero es minuciosamente más lento, pensé que no podía estar en un apuro, ya que estaban convocando a la re.search función de los módulos en el lugar de la re método del objeto. Tirando de regex.search como un método vinculado fuera de la listcomp es otro menor de edad, pero útil de optimización, por cierto.
    • tan pronto como vi tu respuesta me di cuenta de que el uso de re.la búsqueda no fue la mejor manera de ir. Podría usted aclarar que para mí cómo «[tire de la] regex.la búsqueda como un método vinculado fuera de la listcomp»? Realmente aprecio su paciencia con un listcomp y Python noob.
    • lst=[m.grupo(1) de l en las líneas para m en [src(l)] si m] es el «método vinculado elevación» optimización (¿es el método de búsqueda de una vez en lugar de tener que rehacer para cada línea — Python no polipasto atributo búsquedas para usted, cuando usted necesita, tales optimización sin embargo, puede hacerlo manualmente, como lo demostró).
    • Me parece un anidada comprensión más legible que la «doble hack»: search = re.compile('...').search; out = [m.group(1) for m in map(search, lines) if m] Usted podría utilizar corchetes anidados, pero en este caso un mapa() es igual de legible, ya que el transformador es un simple rescatable, y es en realidad más rápido! (33% más rápida que la de hack con una tupla, 40% más rápida que la de hack con una lista de, y un 15% más rápido que una lista anidada de la comprensión de uso de los corchetes.) Mide utilizando un moderadamente complejo regexp '(a.*b.*c)', que es O(n2), en una enorme lista de nombres de archivo.
  2. 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 podría poner todo en una línea, pero eso significaría que tendría que coincidir con cada línea dos veces que sería un poco menos eficiente.

    • Nah, no hay necesidad para que coincida con cada línea dos veces, ver mi respuesta.
    • De hecho, su respuesta es mucho más limpio, +1 de mí 🙂
  3. 1

    De partida Python 3.8, y la introducción de asignación de expresiones (PEP 572) (:= operador), es posible utilizar una variable local dentro de una lista de comprensión con el fin de evitar llamar varias veces la misma expresión:

    # items = ["foo", "bar", "baz", "qurx", "bother"]
    [(x, match.group(1)) for x in items if (match := re.compile('(a|r$)').search(x))]
    # [('bar', 'a'), ('baz', 'a'), ('bother', 'r')]

    Este:

    • Nombres de la evaluación de re.compile('(a|r$)').search(x) como una variable match (que está None o un Match objeto)
    • Utiliza este match denominado expresión en su lugar (ya sea None o un Match) para filtrar la no coincidencia de los elementos
    • Y re-utiliza match en el valor asignado por la extracción del primer grupo (match.group(1)).
  4. -14
    >>> "a" in "a visit to the dentist" 
    True 
    >>> "a" not in "a visit to the dentist" 
    False

    Que también funciona con una consulta de búsqueda que usted está buscando en una lista de

    `P=’a’, ‘b’, ‘c’

    ‘b’ en P` devuelve true

    • ¿Cómo responder a la pregunta?
    • Esta pregunta puede presentar una mejor manera de comprobar las entradas en una lista de re, pero por el camino no funcionan si desea grep resultados. U siempre se puede hacer un bucle sencillo para todo el volver a la salida. No es mucho la diferencia de hacerlo de forma manual de uso de una función que hace lo mismo…

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea