2017-07-04 1 views
1

j'ai une liste de tuples nommé:Python: Vérifiez si la liste des tuples nommés contient une valeur d'attribut particulier

from collections import namedtuple 

T = namedtuple('T', ['attr1', 'attr2', 'attr3', 'attr4']) 
t1 = T('T1', 1, '1234', 'XYZ') 
t2 = T('T2', 2, '1254', 'ABC') 
t3 = T('T2', 2, '1264', 'DEF') 
l = [t1, t2, t3] 

Je veux vérifier si un élément existe dans la liste Tattr1 = 'T2'.

Vérification si la liste contient un tel élément en faisant:

any(x for x in l if x.attr1 == 'T2') 

renvoie uniquement les informations si un tel namedtuple est dans la liste ou non.
Je voudrais également sortir ce namedtuple de la liste.
Une façon de le faire est:

if any(x for x in l if x.attr1 == 'T2'): 
    result = [x for x in l if x.attr1 == 'T2'].pop() 

Cependant, je n'aime pas cette solution, puisque je suis en boucle sur la liste l deux fois.

Existe-t-il une façon de faire plus élégante?

+1

Pas directement une réponse, mais l'habituel 'any' expression pour tester l'existence d'un tel élément serait' tout (x.attr1 == ' T2 'pour x en l) ', pas ce que vous avez. Ce que vous faites repose involontairement sur le fait que vos namedtuples sont considérés comme vrais lorsqu'ils sont traités comme des booléens. En fait, le genexp que vous avez écrit est plus approprié pour extraire un namedtuple correspondant que pour tester l'existence! – user2357112

Répondre

2

Que diriez-vous d'une ancienne boucle de boucle? Simple, élégant, et vous bouclez une seule fois.

for x in l: 
    if x.attr1 == 'T2': 
     break 

result = x 
1

Ou vous pouvez utiliser next:

try: 
    result = next(t for t in l if t.attr1 == 'T2') 
except StopIteration: 
    result = None 

result 
# T(attr1='T2', attr2=2, attr3='1254', attr4='ABC') 
+0

Identique à 'result = next ((t pour t dans l si t.attr1 == 'T5'), None)', seulement plus long. Utiliser 'bare' est une mauvaise idée. – vaultah

+0

@Psidom Je l'ai downvoted principalement parce que votre réponse était l'enseignement de la mauvaise pratique (nu «sauf»). – vaultah

1

Si vous avez besoin d'un élément et ne veulent pas nécessairement à la pop, vous pouvez utiliser next avec votre expression de générateur existant:

result = next(x for x in l if x.attr1 == 'T2') 
1

S'il est permis d'obtenir le résultat sous forme de tableau:

result = filter(lambda x: x.attr1 == 'T2', l) 

Ou si vous voulez juste obtenir un alors:

result = filter(lambda x: x.attr1 == 'T2', l).pop()