web-dev-qa-db-fra.com

Comment utiliser re match objets dans une liste de compréhension

J'ai une fonction pour choisir des grumeaux dans une liste de chaînes et les renvoyer comme une autre liste:

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

Existe-t-il un moyen de reformuler cela comme une compréhension de liste? Évidemment, c'est assez clair tel quel; juste curieux.


Merci à ceux qui ont contribué, mention spéciale pour @Alex. Voici une version condensée de ce que j'ai fini avec; la méthode de correspondance d'expressions régulières est transmise à filterPick en tant que paramètre "pré-hissé":

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')]
41
Brent.Longborough
[m.group(1) for l in lines for m in [regex.search(l)] if m]

L'astuce est la partie for m in [regex.search(l)] - c'est ainsi que vous "assignez" une valeur que vous devez utiliser plus d'une fois, dans une liste de compréhension - ajoutez simplement une telle clause, où l'objet "itère" "sur une liste d'éléments contenant la seule valeur que vous souhaitez" lui attribuer ". Certains considèrent cela douteux sur le plan stylistique, mais je le trouve parfois pratique.

70
Alex Martelli
return [m.group(1) for m in (re.search(regex, l) for l in lines) if m]
10

Cela pourrait être un peu raccourci

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

Vous pourriez tout mettre sur une seule ligne, mais cela signifierait que vous devriez faire correspondre chaque ligne deux fois, ce qui serait un peu moins efficace.

7
Wolph

A partir de Python 3.8, Et l'introduction de expressions d'affectation (PEP 572) (opérateur :=), Il est possible d'utiliser une variable locale dans une liste de compréhension afin d'éviter appelant plusieurs fois la même expression:

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

Cette:

  • Nomme l'évaluation de re.compile('(a|r$)').search(x) en tant que variable match (qui est soit None soit un objet Match)
  • Utilise cette expression nommée match en place (None ou Match) pour filtrer les éléments non correspondants
  • Et réutilise match dans la valeur mappée en extrayant le premier groupe (match.group(1)).
1
Xavier Guihot