TL; DR
A generator expression is probably the most efficient and easiest solution to your problem:
l = [(1,"juca"),(22,"james"),(53,"xuxa"),(44,"delicia")] result = next((i for i, v in enumerate(l) if v[0] == 53), None)
Explanation
There are several answers that provide a simple solution to this combo box question. Although these answers are perfectly correct, they are not optimal. Depending on your use case, there can be significant benefits to making a few simple changes.
The main problem that I see when using list comprehension for this use case is that the whole list will be processed, although you only want to find 1 element.
Python provides a simple construct that is ideal here. It is called an expression. Here is an example:
We can expect this method to do basically the same thing as the list in our trivial example, but what if we work with a large dataset? That is where the advantage of using the generator method comes into play. Instead of creating a new list, we will use your existing list as our iterable and use next() to get the first element from our generator.
Let's see how these methods work differently on some large datasets. These are large lists consisting of 10,000,000 + 1 elements, with our goal in the beginning (best) or ending (worst). We can verify that both of these lists will work equally using the following list:
Listing
"Worst case"
worst_case = ([(False, 'F')] * 10000000) + [(True, 'T')] print [i for i, v in enumerate(worst_case) if v[0] is True]
"The best case"
best_case = [(True, 'T')] + ([(False, 'F')] * 10000000) print [i for i, v in enumerate(best_case) if v[0] is True]
Generator Expressions
Here is my hypothesis for generators: we will see that generators will work much better in the best case, but similarly in the worst case. This performance increase is mainly due to the fact that the generator is evaluated lazily, that is, it will only calculate what is required to obtain the value.
Worst case
Best case
best_case = [(True, 'T')] + ([(False, 'F')] * 10000000) print next((i for i, v in enumerate(best_case) if v[0] == True), None)
WHAT?! The best case resets understanding of lists, but I did not expect our worst case to exceed correspondence to such an extent. How so? Honestly, I could only speculate without further research. Maybe I'll ask about it.
Take it all with a piece of salt, I haven't done any solid profiling here, just some very simple tests. I would like to include some memory profiling, but these methods are running away from me. However, what we see here is enough to see that the expression for the generator is more efficient for finding this type in the list.
Please note that this is all basic, built-in python. We do not need to import anything or use special libraries.
And to give credit, when credit should be, I first saw this technique in a free course, Udacity cs212 with Peter Norwig.