2011-04-13 2 views
2

Étant donné une liste d'instances, dites clients J'essaie de retirer un élément de la liste en fonction de la valeur d'une seule variable d'instance screenName. Je sais que je peux le faire:Python obtenir instance à partir de la liste basée sur la variable d'instance

for client in clients: 
    if client.screenName = search: 
    return client 

Mais y a-t-il une meilleure façon de le faire sans la boucle?

Merci pour votre aide :)

+2

Je suppose que vous voulez dire client.screen == recherche –

Répondre

6

Vous pouvez utiliser filter

try: 
    filter(lambda client: client.screenName == search, clients)[0] 
except IndexError: 
    # handle error. May be use a default value 
+0

Cela n'augmentera-t-il pas 'IndexError' si le client ** no ** des clients a' screenName == search'? ... – neurino

+0

@neurino J'ai supposé que l'exception serait gérée. Mais ajouté le bloc 'try-except' par souci d'exhaustivité. –

+0

Je supprimerais simplement le '[0]' et retournerais une liste de résultats. Après tout, il pourrait y avoir plus d'un match, alors si seulement le premier est nécessaire ... – neurino

0

en utilisant un dictionnaire pour cela:

supposant ceci:

d[screeName] = client 

vous pouvez simplement le faire:

return d[search] 
0

Si clients est un dict alors vous pouvez simplement utiliserdix . Si l'ordre des éléments de votre liste est important, vous pouvez utiliser un OrderedDict de collections.

1

Je voudrais utiliser list comprehensions. Supposons que ceci est votre Client classe:

>>> class Client: 
... def __init__(self, screenName): 
...  self.screenName = screenName 

Si je suis arrivé cette liste de clients:

>>> l = [Client('a'), Client('b'), Client('c')] 

... Je peux obtenir une liste ne contenant que les clients ayant un nom donné:

>>> [e for e in l if e.screenName == 'b'] 
[<__main__.Client instance at 0x2e52b0>] 

maintenant, juste obtenir le premier - et seulement en supposant qu'il - élément:

>>> [e for e in l if e.screenName == 'b'][0] 
<__main__.Client instance at 0x2e52b0> 
>>> c = [e for e in l if e.screenName == 'b'][0] 
>>> c.screenName 
'b' 

Ceci est assez court et élégant à mon humble avis, mais peut être moins efficace parce que la compréhension de la liste va parcourir toute la liste. Si vous ne voulez éviter cette surcharge, vous pouvez obtenir un générateur au lieu d'une nouvelle liste à l'aide entre parenthèses plutôt que de crochets:

>>> g = (e for e in l if e.screenName == 'b') 
>>> g 
<generator object <genexpr> at 0x2e5440> 
>>> g.next() 
<__main__.Client instance at 0x2e52b0> 

Cependant, notez que la méthode next() peut être appelée une seule fois.

HTH!

+0

Très concis et agréable. Je suppose que next() peut être appelé plusieurs fois si l contient plusieurs objets avec le même nom d'écran. – Daniel

1

Vous pouvez utiliser un generator expression,

client=next(client for client in clients if client.screenName == search) 

mais pas encore que vous en boucle, juste d'une manière différente.

Remarque: Si aucun client ne satisfait à la condition client.screenName == search, alors ce qui précède déclenchera une exception StopIteration. Ceci est différent de votre for-loop, qui tombe hors de la boucle sans rien retourner. En fonction de votre situation, lever une exception peut être préférable à un échec en mode silencieux.

Si vous ne voulez pas une valeur par défaut au lieu d'une StopIteration exception, alors vous pouvez utiliser la version 2 paramètres de next:

client=next(client for client in clients if client.screenName == search, 
      default_value) 
0

meilleure discussion sur ce sujet est sur ce link

return find(lambda client: client.screenName == search, clients) 

Cela nécessite de définir une fonction de recherche générique qui fonctionne pour tous les types de listes comme ainsi:

def find(f, seq): 
    """Return first item in sequence where f(item) == True.""" 
    for item in seq: 
    if f(item): 
     return item 
+0

Je pense que vous voulez dire 's/find/filter /'? –

+0

non je voulais dire ce que j'ai écrit, ne pas obtenir le downvote. Voir ici: http://tomayko.com/writings/cleanest-python-find-in-list-function – Yasser

+0

bien vous devriez définir 'trouver' dans votre réponse ..however .. – Ant

Questions connexes