Ziva
Ziva

Reputation: 3501

Python: Check if list of named tuples contains particular attribute value

I have a list of named tuples:

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]

I want to check if an element exists in the list T where attr1 = 'T2'.

Checking if the list contains such an element by doing:

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

only returns the information whether such a namedtuple is in the list or not.
I would like to also pop this namedtuple from the list.
One way of doing it is:

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

However, I don't like this solution, since I'm looping over the list l twice.

Is there any better/more-elegant way of doing this?

Upvotes: 7

Views: 5076

Answers (4)

Gabriel Ecker
Gabriel Ecker

Reputation: 102

If it is allowed to get the result as an array:

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

Or if you just want to get one then:

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

Upvotes: 1

akuiper
akuiper

Reputation: 214967

Or you can use 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')

Upvotes: 1

Moses Koledoye
Moses Koledoye

Reputation: 78554

If you need one item and don't necessarily want to pop, you can use next with your existing generator expression:

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

Upvotes: 2

cs95
cs95

Reputation: 402553

How about an old-school for loop? Simple, elegant, and you loop only once.

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

result = x

Upvotes: 3

Related Questions