2010-11-02 13 views
5

Kelimelerin bir listesini almam ve 2 veya daha fazla karakter uzunluğunda ve ilk ve son karakterin eşit olduğu tüm kelimeleri saymam gerekiyor. Tercih çözüm olacaktır0 kavrama ve len() vs. döngü için basit

result = 0 
for word in words: 
    if len(word) >= 2 and word[0] == word[-1]: 
     result += 1 
return result 

vs

return len([word for word in words if len(word) >= 2 and word[0] == word[-1]]) 

:

iki olası çözümler ile geldi? Yoksa daha da iyisi var mı?

+0

# 2 alırım; ancak çok satırlı olarak güzel biçimlendirilmiş. Sadece bir tane yazabileceğinden, bir satır yazmanız gerektiği anlamına gelmez (jeneratörler veya for-comp ile bile) –

+0

Lütfen, lütfen, lütfen ölçün. Bunu ölçmek için lütfen "timeit" i kullanın. Lütfen sonuçları ölçün ve gönderin. –

+1

@ S.Lott: Performans hakkında hiçbir şey söylemedi. Bir şey yapmanın * tercih edilen * yolu bir şey yapmanın * en hızlı * yolunu göstermez. –

cevap

14

İkinci örneğinizde, listeniz büyükse, bir generator expression liste-comp daha iyi olurdu.

sum(1 for word in words if len(word) >= 2 and word[0] == word[-1]) 
+1

TypeError: 'generator' türünde nesnenin numarası yok() – dan04

+0

Teşekkürler! Bunu neredeyse önerecektim. – pyfunc

+0

@ dan04: teşekkürler; şimdi düzeltildi. @pyfunc: teşekkürler! – bernie

1

Her ikisi de oldukça iyi.

Liste anlama sen len geçirerek başka bir liste döndürür:

küçük farklılıklar vardır. İlk çözüm başka bir listenin oluşturulmasını engeller.

3

Birincisi Python'da kesinlikle tercih edilen çözüm olacaktır.

Python senin Zen unutmayın: sizin çözümleri iyi olduğunu

The Zen of Python, by Tim Peters

Beautiful is better than ugly.

Explicit is better than implicit.

Simple is better than complex.

Complex is better than complicated.

Flat is better than nested.

Sparse is better than dense.

Readability counts.

Special cases aren't special enough to break the rules.

Although practicality beats purity.

Errors should never pass silently.

Unless explicitly silenced.

In the face of ambiguity, refuse the temptation to guess.

There should be one-- and preferably only one --obvious way to do it.

Although that way may not be obvious at first unless you're Dutch.

Now is better than never.

Although never is often better than right now.

If the implementation is hard to explain, it's a bad idea.

If the implementation is easy to explain, it may be a good idea.

Namespaces are one honking great idea -- let's do more of those!

Diğer daha.

+4

Python-papağan-zenlemenin genel formülü: bir iddiada bulunun ve bir metin olarak, sanki bazı dini metinler gibi bir gerekçelendirin. (İkinci versiyonu çok net buluyorum; ilk önce C.'den bir şey gibi görünüyor) –

+0

Tamamen katılmıyorum. Anlamaların listesi * çok * Pythonic ve okunabilir. –

2

Ben şahsen açık döngüyü daha okunaklı buluyorum, ama bu bir tat meselesi (bazıları, özellikle yazmaları gerektiğinde daha kısa kodları tercih eder).

Ya sürüm ayrıca/iyileştirilmiş kısaltılabilir: 1 bir tür Doğru beri

result = 0 
for word in words: 
    result += int(len(word) >= 2 and word[0] == word[-1]) 
return result 

int() dönüşümleri kesinlikle gereksiz konuşuyor, ancak okunabilir olması için daha iyi olabilir.

len(1 for word in words if len(word) >= 2 and word[0] == word[-1]) 
+0

'a + = int (bool)', kötülük dediğim noktaya tekdüzedir. Bunu yapma; Orijinal durum daha açık. –

1

: Eğer len() kullanmak istiyorsanız, ben değerleri gerçekten önemli değil gerçeğine okuyucuyu işaret ediyorum

return sum(len(word) >= 2 and word[0] == word[-1] for word in words) 

: Aynı yaklaşım anlama uygulayabileceğiniz Dikkate almak isteyebileceğiniz diğer bazı varyantlar:

İlk olarak, filtre koşulunu bir işleve ayırabilirsiniz. Bu durum her iki durumda da iyi, ama artık karmaşık hale gelirse ben kesinlikle bu yapardım:

def check(word): 
    return len(word) >= 2 and word[0] == word[-1] 
sum(1 for word in words if check(word)) 

Sonraki kabul edilebilir (orijinal liste anlama olduğu gibi) bir liste oluşturulması, o zaman bunu yapabilirsiniz : Orada itertools.ifilter ama

len(filter(check, words)) 

Eğer tekrar sum ifadesini kullanmak gerektiğini kullanıyorum o yüzden daha açık sona etmezse.

sum hilesi o kadar sık ​​gelir ki, bir yineleyicideki öğelerin sayısını saymak için standart bir kütüphane çağrısı olmadığına şaşırdım (eğer bulamıyorsam, onu bulamadım). Alternatif olarak, __len__ ise, len'un bir yineleyicideki giriş sayısını tüketir ve saymazsa, anlamlı olur.