2010-11-02 81 views
5

我應該採取單詞列表並計算其中的所有單詞,它是2個或更多字符長,第一個和最後一個字符相等。列表理解和len()與簡單for循環

我想出了兩種可能的解決方案:

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

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

哪一個將是首選的解決方案?或者還有更好的嗎?

+0

我會採取#2:但格式很好,在多行。僅僅因爲你*可以*寫它一行並不意味着你應該(即使有發電機或補償等) – 2010-11-03 00:08:04

+0

請請,請測量。請使用'timeit'來衡量。請測量併發布結果。 – 2010-11-03 01:17:07

+1

@ S.洛特:他對演出一無所知。 *首選*做某事的方式並不意味着最快的做法。 – 2010-11-03 09:05:04

回答

14

在第二個例子中,如果列表很大,那麼generator expression會比list-comp更好。

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

TypeError:'generator'類型的對象沒有len() – dan04 2010-11-02 23:51:17

+0

謝謝!我幾乎會建議它。 – pyfunc 2010-11-02 23:51:37

+0

@ dan04:謝謝;現在修好。 @pyfunc:謝謝! – bernie 2010-11-02 23:55:21

1

兩者都很不錯。

有小的差異:

列表理解返回其要傳遞到LEN另一個列表。第一種解決方案避免了創建另一個列表。

3

第一個肯定是Python中的首選解決方案。

不要忘記你的禪的Python:

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!

除此之外,您的解決方案是好的。

+4

通常的Python-parroting的公式:提出一個聲明,並將其作爲理由指向一條線,就好像它是一些宗教文本。 (我發現第二個版本非常清晰;第一個看起來像從C移植過來的東西)。 – 2010-11-03 00:03:28

+0

我完全不同意。列表理解*非常* Pythonic和可讀。 – 2010-11-03 03:12:07

2

我個人發現這個顯式循環更具可讀性,但它有很大的味道(有些人更喜歡較短的代碼,特別是當他們必須編寫代碼時)。

任一版本可以進一步縮短的/改進:

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

的int()轉換嚴格地說不必要的,因爲真正的是一種如圖1所示,但它可以是用於可讀性更好。同樣的方法也適用於理解:

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

如果你想使用LEN(),我想讀者指出,事實上,這些值並不真正的問題:

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

'a + = int(bool)'是單一的,我稱它爲邪惡。不要那樣做;原來的情況更加清晰。 – 2010-11-03 00:14:55

1

您可能要考慮的其他一些變體:

首先,您可以將過濾條件分解爲函數。這狀況良好無論哪種方式,但如果它變得更多複雜的,我肯定會做到這一點:

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

接下來,如果生成列表(如在原始列表理解)是可以接受的,那麼你可以這樣做:

len(filter(check, words)) 

有itertools.ifilter,但如果你使用,你需要再次使用sum表達,所以它不會落得更清楚。

sum這個技巧經常出現,我很驚訝沒有標準的庫調用來計算迭代器中的項數(如果有的話,我沒有找到它)。或者,如果len會消耗並計算迭代器中的條目數(如果它沒有__len__),但它不會。