2013-02-01 84 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)