2013-02-01 83 views
7

什麼是得到最長的單詞的長度更Python的方式:長度最長的單詞的

len(max(words, key=len))

或者:

max(len(w) for w in words)

或..別的東西? words是一個字符串列表。 我發現我需要經常這樣做,在計算好幾個不同的樣本數後,第一種方式似乎始終快一些,儘管在面值方面看起來效率較低(冗餘的len被稱爲兩次似乎無關緊要 - 更多在這種形式的C代碼中發生?)。

+0

@isedev那會給這個詞,而不是詞 –

+2

個人而言,我更喜歡後者的長度,看起來更漂亮 – Wolph

+4

''LEN(MAX(也就是說,鍵= LEN))''好因爲它作爲一個*哦,我忘了''max''把鑰匙作爲參數。*提醒溼件。 – sotapme

回答

5

我覺得都是正常的,但我認爲,除非速度是一大考慮到max(len(w) for w in words)是最可讀的。

當我看着它們時,我花了更長的時間才弄清楚len(max(words, key=len))在做什麼,而且在我考慮更多之前我仍然是錯誤的。代碼應該立即顯而易見,除非有充分的理由不這樣做。

從其他帖子(以及我自己的測試)可以看出,可讀性較差的文章更快。但是,這不是他們中的任何一個都很慢。除非代碼處於關鍵路徑,否則不值得擔心。

最終,我認爲更可讀的是更Pythonic。另外,這是少數情況下Python 2比Python 3在同一任務中速度明顯更快的情況之一。

+0

在我的測試中,3.3.0爲我能想到的每個版本都打2.7.2。 (請參閱我的答案,以明顯的。) – abarnert

+0

更新:實際上,如果我在32位模式下運行它們,則3.3.0顯着較慢。但是,至少在Mac電腦上,幾乎所有的東西在32位3.2或3.3中似乎都很慢,所以我不認爲這種情況有任何特定的含義。 – abarnert

+0

@abarnert:有趣。我在Linux系統上以64位模式運行它們。一個是Python 2.7.3,另一個是3.3.0。我使用'/ usr/share/dict/words'作爲單詞列表。我的速度是88ms vs 66ms。也許這是我選擇的一個長長的單詞列表,它有所不同。 – Omnifarious

1

我想說

len(max(x, key=len)) 

看起來相當不錯,因爲你使用的內置(max)關鍵字參數(key)與內置(len)。所以基本max(x, key=len)幾乎可以得到答案。但是你的代碼變體對我來說看起來並不那麼矛盾。

+1

但*爲什麼*?有什麼理由嗎? – arshajii

+0

@ A.R.S .:增加了一個簡短的,好的......主觀原因。 – miku

8

雖然:

max(len(w) for w in words) 

做樣的「閱讀」更容易 - 你有一臺發電機的開銷。

雖然:

len(max(words, key=len)) 

可以優化掉使用內建的關鍵,自len通常是一個非常有效的運算字符串,將是更快......

+1

這就是說 - 我不能說哪個更「Pythonic」 - 我喜歡這兩種,但對於不熟悉'key'的'max'使用的人來說,前者可能會立刻變得更加可靠 –

0

只爲信息使用ipython %timeit

In [150]: words 
Out[150]: ['now', 'is', 'the', 'winter', 'of', 'our', 'partyhat'] 

In [148]: %timeit max(len(w) for w in words) 
100000 loops, best of 3: 1.87 us per loop 

In [149]: %timeit len(max(words, key=len)) 
1000000 loops, best of 3: 1.35 us per loop 

剛剛更新了更多的單詞來演示@ Omnifarious的觀點/評論。

In [160]: words = map(string.rstrip, open('/usr/share/dict/words').readlines()) 

In [161]: len(words) 
Out[161]: 235886 

In [162]: %timeit max(len(w) for w in words) 
10 loops, best of 3: 44 ms per loop 

In [163]: %timeit len(max(words, key=len)) 
10 loops, best of 3: 25 ms per loop 
+0

作爲列表時間越長,差異越大。 – Omnifarious

3

如果您將生成器表達式重寫爲map調用(或者對於2。X,imap):

max(map(len, words)) 

...它實際上是一個有點比密鑰版本,而不是更慢速度更快。

python.org 64位3.3.0:

In [186]: words = ['now', 'is', 'the', 'winter', 'of', 'our', 'partyhat'] * 100 
In [188]: %timeit max(len(w) for w in words) 
%10000 loops, best of 3: 90.1 us per loop 
In [189]: %timeit len(max(words, key=len)) 
10000 loops, best of 3: 57.3 us per loop 
In [190]: %timeit max(map(len, words)) 
10000 loops, best of 3: 53.4 us per loop 

蘋果64位2.7.2:

In [298]: words = ['now', 'is', 'the', 'winter', 'of', 'our', 'partyhat'] * 100 
In [299]: %timeit max(len(w) for w in words) 
10000 loops, best of 3: 99 us per loop 
In [300]: %timeit len(max(words, key=len)) 
10000 loops, best of 3: 64.1 us per loop 
In [301]: %timeit max(map(len, words)) 
10000 loops, best of 3: 67 us per loop 
In [303]: %timeit max(itertools.imap(len, words)) 
10000 loops, best of 3: 63.4 us per loop 

我覺得它比key版本更Python,出於同樣的原因genexp是。

這是值得爭議的是它是pyxonic作爲genexp版本。有人喜歡map/filter/reduce/etc;有些討厭他們;我個人的感覺是,當你試圖映射一個已經存在並且名字很好的函數(也就是說,你不需要lambdapartial),map更好,但是YMMV(尤其是如果你的名字是Guido)。

最後一點:

LEN被調用兩次冗餘似乎並不重要 - 沒有更多的發生在C代碼以這種形式?

想想這樣:你已經撥打了len N次。調用它N+1次反而幾乎不可能有所作爲,相比之下你要做的任何事情N次,除非你有一個微小的巨大的字符串。

+0

'max(map (len,words))'也是非常可讀和明顯的。所以它得到我的投票。 – Omnifarious

+0

@Omnifarious:它對我來說是可讀的,對你而言是顯而易見的,但對你而言......但也許對每個人都不是。我添加了一個關於這個的段落。 – abarnert

-1

我知道它已經現在開始的一年,但neverthless,我想出了這個:

「」「寫一個函數find_longest_word(),它的單詞和 返回最長的一個的長度的名單。」 ''

a = ['mamao', 'abacate', 'pera', 'goiaba', 'uva', 'abacaxi', 'laranja', 'maca'] 

def find_longest_word(a): 

    d = [] 
    for c in a: 
     d.append(len(c)) 
     e = max(d) #Try "min" :D 
    for b in a: 
     if len(b) == e: 
      print "Length is %i for %s" %(len(b), b)