tl; dr
Bir üreteç ifadesi muhtemelen sorununuzun en yüksek performanslı ve basit çözümüdür:
l = [(1,"juca"),(22,"james"),(53,"xuxa"),(44,"delicia")]
result = next((i for i, v in enumerate(l) if v[0] == 53), None)
Açıklama
Bu soruya liste anlayışıyla basit bir çözüm sağlayan birkaç cevap vardır. Bu cevaplar tamamen doğru olsa da optimal değildir. Kullanım durumunuza bağlı olarak, birkaç basit değişiklik yapmanın önemli faydaları olabilir.
Bu kullanım senaryosu için bir liste kavrama kullanırken gördüğüm ana sorun , yalnızca 1 öğeyi bulmak istemenize rağmen tüm listenin işlenecek olmasıdır .
Python, burada ideal olan basit bir yapı sağlar. Oluşturucu ifadesi denir . İşte bir örnek:
l = [(1,"juca"),(22,"james"),(53,"xuxa"),(44,"delicia")]
next((i for i, v in enumerate(l) if v[0] == 53), None)
Bu yöntemin, önemsiz örneğimizdeki liste anlamalarıyla temelde aynı performansı göstermesini bekleyebiliriz, ancak ya daha büyük bir veri kümesiyle çalışıyorsak? Jeneratör yöntemini kullanmanın avantajı burada devreye giriyor. Yeni bir liste oluşturmak yerine, mevcut listenizi yinelenebilir olarak kullanacağız next()
ve oluşturucumuzdan ilk öğeyi almak için kullanacağız .
Bu yöntemlerin bazı büyük veri kümelerinde nasıl farklı performans gösterdiğine bakalım. Bunlar 10000000 + 1 elementten oluşan, hedefimizin başında (en iyi) veya sonunda (en kötü) olan büyük listelerdir. Aşağıdaki liste anlayışını kullanarak bu listelerin her ikisinin de eşit performans göstereceğini doğrulayabiliriz:
Anlayışları listeleyin
"En kötü durumda"
worst_case = ([(False, 'F')] * 10000000) + [(True, 'T')]
print [i for i, v in enumerate(worst_case) if v[0] is True]
"En iyi senaryo"
best_case = [(True, 'T')] + ([(False, 'F')] * 10000000)
print [i for i, v in enumerate(best_case) if v[0] is True]
Jeneratör ifadeleri
İşte jeneratörler için hipotezim: Jeneratörlerin en iyi durumda önemli ölçüde daha iyi performans göstereceğini, ancak en kötü durumda da benzer şekilde performans göstereceğini göreceğiz. Bu performans kazancı, çoğunlukla jeneratörün tembel olarak değerlendirilmesinden kaynaklanmaktadır, yani sadece bir değer elde etmek için gerekli olanı hesaplayacaktır.
En kötü durumda
En iyi senaryo
best_case = [(True, 'T')] + ([(False, 'F')] * 10000000)
print next((i for i, v in enumerate(best_case) if v[0] == True), None)
NE?! En iyi durum liste anlayışlarını ortadan kaldırır, ancak en kötü durumumuzun liste anlayışlarından bu kadar daha iyi performans göstermesini beklemiyordum. Bu nasıl? Açıkçası, daha fazla araştırma yapmadan sadece spekülasyon yapabilirdim.
Tüm bunları bir tuz parçasıyla alın, burada sağlam bir profilleme yapmadım, sadece çok basit bir test. Bu, bir üretici ifadesinin bu tür liste araştırması için daha performanslı olduğunu anlamak için yeterli olmalıdır.
Bunun tümünün temel, yerleşik python olduğunu unutmayın. Hiçbir şey içe aktarmamıza veya herhangi bir kitaplık kullanmamıza gerek yok.
Bu tekniği ilk olarak Peter Norvig ile Udacity cs212 kursunda arama yaparken gördüm .