Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 274
Jens Avatar asked Apr 03 '15 02:04

Jens


2 Answers

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.

like image 196
Óscar López Avatar answered Oct 26 '22 13:10

Óscar López


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
like image 42
alecxe Avatar answered Oct 26 '22 12:10

alecxe