2010-03-12 7 views
37

J'ai une fonction pour choisir des morceaux à partir d'une liste de chaînes et de les retourner comme une autre liste:Comment utiliser des objets re match dans une compréhension de la liste

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

est-il un moyen de reformuler cela comme une liste compréhension? De toute évidence, c'est assez clair tel quel; juste curieux.


Merci à ceux qui ont contribué, une mention spéciale pour @Alex. Voici une version condensée de ce que j'ai fini avec; la méthode de match regex est passé à filterPick comme paramètre « pré-hissés »:

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

Répondre

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

Le « truc » est la for m in [regex.search(l)] partie - c'est comment vous « assigner » une valeur que vous devez utiliser plus d'une fois, dans une liste de compréhension - ajouter juste une telle clause, où l'objet "itère" sur une liste d'un seul élément contenant la valeur que vous voulez lui "assigner". Certains trouvent cela stylistiquement douteux, mais je le trouve parfois pratique.

+1

Alex, j'aime ça; merci et +1. J'ai un peu de lourdeur à faire avec ce code - devrais-je m'inquiéter des frais supplémentaires de mise en place et de démontage du "faux itérateur"? BTW Je souscris à la doctrine de "optimiser plus tard". –

+1

@Brent, le "faux itérateur" devrait être négligeable par rapport à l'appel de recherche; une optimisation mineure consiste à utiliser '(regex.search (l),)' à la place de '[regex.search (l)]' (que je trouve plus lisible mais qui est minutieusement plus lent - je pensais que vous ne pouviez pas être pressé comme vous appeliez réellement la fonction 're.search' du module plutôt que la méthode de l'objet re.Tirer' regex.search' comme méthode liée en dehors du listcomp est une autre optimisation mineure mais utile, comme –

+0

Dès que j'ai vu votre réponse, je me suis rendu compte que l'utilisation de re.search n'était pas la meilleure solution. Pourriez-vous clarifier pour moi comment vous "[tirer le] regex.search comme une méthode liée en dehors du listcomp"? votre patience avec un listcomp et Python noob –

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

Il pourrait être un peu raccourcies

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

Vous pouvez le mettre en une seule ligne, mais cela voudrait dire que vous devez faire correspondre chaque ligne deux fois ce qui serait un peu moins efficace.

+2

Nah, pas besoin de faire correspondre chaque ligne deux fois, voir ma réponse. –

+0

En effet, votre réponse est beaucoup plus propre, +1 de moi :) – Wolph

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

Cela fonctionne aussi avec une requête de recherche vous pourchassant dans une liste

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

'b' dans p` retourne vrai

+1

Comment cela répond-il à la question? –

+0

Ces questions peuvent présenter un meilleur moyen de vérifier les entrées dans une liste que re, mais d'ailleurs ne fonctionnent pas si vous ne voulez pas grep résultats. Vous pouvez toujours faire une simple boucle autour de la sortie re. Il n'y a pas beaucoup de différence pour le faire manuellement que d'utiliser une fonction qui fait la même chose ... – erm3nda