Reputation: 9130
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
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
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
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