Jens
Jens

Reputation: 9130

Python: search through list of tuples

I have a list of tuples, e.g.

>>> l = [ ("a",1), ("b",2), ("c",3) ]

and I can assume that elements are unique. Now I would like to get the first element of that tuple whose second element is 2 (which is 'b' in this example). First attempt is:

>>> [ x for x, y in l if y == 2 ][0]
'b'

This seems somewhat cumbersome considering this creates a second list only to index the 0th element. Another way of doing this is to reverse all tuples in the given list l and build a dictionary, then index that dictionary:

>>> dict([ (y, x) for x, y in l ])[2]
'b'

This seems even more awkward considering the amount of data shuffling involved in reversing the list and creating a dictionary. Lastly, the most verbose but perhaps fastest way to do this is to simply iterate over the list:

>>> def get(l) :
...     for x, y in l :
...         if y == 2 : 
...             return x
...     assert not "Should not happen."
... 
>>> get(l)
'b'

My question is: are there any better and more pythonic ways to searching through this list?

Upvotes: 6

Views: 7398

Answers (3)

flycee
flycee

Reputation: 12716

It depends on how to wish to pay, space or time. Your could not have both.

1 If we want to speed up:

l = [ ("a",1), ("b",2), ("c",3) ]
_dict = {k:v for v,k in l}
print(_dict.get(2, None))

2 If space is limited, try the other answer's next or your loop.

Upvotes: 1

Óscar López
Óscar López

Reputation: 236034

Try this:

next(x for x in l if x[1] == 2)[0]

The advantage of using next() is that we iterate only over the minimum amount of elements required for finding what we're looking for, so no, it's not equivalent to creating a whole new list using a list comprehension and then returning the first element.

Upvotes: 7

alecxe
alecxe

Reputation: 473893

You can also use next():

In [1]: l = [("a", 1), ("b", 2), ("c", 3)]

In [2]: next(a for a, b in l if b == 2)
Out[2]: 'b'

Note that it would throw StopIteration exception if nothing found unless a default is supplied:

In [3]: next(a for a, b in l if b == 100)
---------------------------------------------------------------------------
StopIteration                             
Traceback (most recent call last)
<ipython-input-38-14fe91d87aab> in <module>()
----> 1 next(a for a, b in l if b == 100)

StopIteration: 

In [4]: next((a for a, b in l if b == 100), 0)
Out[4]: 0

Upvotes: 3

Related Questions