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')]
[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.
return [m.group(1) for m in (re.search(regex, l) for l in lines) if m]
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.
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:
re.compile('(a|r$)').search(x)
en tant que variable match
(qui est soit None
soit un objet Match
)match
en place (None
ou Match
) pour filtrer les éléments non correspondantsmatch
dans la valeur mappée en extrayant le premier groupe (match.group(1)
).