tl; dr
Wyrażenie generator jest prawdopodobnie najbardziej wydajnych i proste rozwiązanie problemu:
l = [(1,"juca"),(22,"james"),(53,"xuxa"),(44,"delicia")]
result = next((i for i, v in enumerate(l) if v[0] == 53), None)
Wyjaśnienie
Istnieje kilka odpowiedzi, które zapewniają proste rozwiązanie tego pytania ze zrozumieniem listy. Chociaż te odpowiedzi są całkowicie poprawne, nie są optymalne. W zależności od przypadku użycia wprowadzenie kilku prostych modyfikacji może przynieść znaczące korzyści.
Główny problem, jaki widzę przy używaniu funkcji rozumienia listy w tym przypadku użycia, polega na tym, że cała lista zostanie przetworzona, chociaż chcesz znaleźć tylko 1 element .
Python zapewnia prostą konstrukcję, która jest tutaj idealna. Nazywa się to wyrażeniem generatora . Oto przykład:
l = [(1,"juca"),(22,"james"),(53,"xuxa"),(44,"delicia")]
next((i for i, v in enumerate(l) if v[0] == 53), None)
Możemy oczekiwać, że ta metoda będzie działać w zasadzie tak samo jak składanie list w naszym trywialnym przykładzie, ale co, jeśli pracujemy z większym zestawem danych? W tym miejscu pojawia się zaleta korzystania z metody generatora. Zamiast tworzyć nową listę, użyjemy istniejącej listy jako naszej iterowalnej i użyjemy next()
do pobrania pierwszego elementu z naszego generatora.
Przyjrzyjmy się, jak te metody działają inaczej na niektórych większych zbiorach danych. Są to duże listy, składające się z 10000000 + 1 elementów, z naszym celem na początku (najlepsza) lub na końcu (najgorsza). Możemy sprawdzić, czy obie te listy będą działać jednakowo, korzystając z następującego rozumienia list:
Lista zdań
"Najgorszy przypadek"
worst_case = ([(False, 'F')] * 10000000) + [(True, 'T')]
print [i for i, v in enumerate(worst_case) if v[0] is True]
„Najlepszy przypadek”
best_case = [(True, 'T')] + ([(False, 'F')] * 10000000)
print [i for i, v in enumerate(best_case) if v[0] is True]
Wyrażenia generatora
Oto moja hipoteza dotycząca generatorów: zobaczymy, że generatory będą działać znacznie lepiej w najlepszym przypadku, ale podobnie w najgorszym. Ten wzrost wydajności wynika głównie z faktu, że generator jest oceniany leniwie, co oznacza, że oblicza tylko to, co jest wymagane do uzyskania wartości.
Najgorszy przypadek
Najlepszy przypadek
best_case = [(True, 'T')] + ([(False, 'F')] * 10000000)
print next((i for i, v in enumerate(best_case) if v[0] == True), None)
CO?! Najlepszy przypadek niszczy listy składane, ale nie spodziewałem się, że nasz najgorszy przypadek będzie lepszy od rozumienia list w takim stopniu. W jaki sposób? Szczerze mówiąc, mogłem tylko spekulować bez dalszych badań.
Weź to wszystko z przymrużeniem oka, nie przeprowadziłem tutaj żadnego solidnego profilowania, tylko kilka bardzo podstawowych testów. Powinno to wystarczyć, aby zdać sobie sprawę, że wyrażenie generatora jest bardziej wydajne dla tego typu wyszukiwania list.
Zauważ, że to wszystko jest podstawowym, wbudowanym Pythonem. Nie musimy niczego importować ani używać żadnych bibliotek.
Po raz pierwszy zobaczyłem tę technikę wyszukiwania na kursie Udacity cs212 z Peterem Norvigiem.