7

获取最长单词长度的更pythonic方法是什么:

len(max(words, key=len))

或者:

max(len(w) for w in words)

或者是其他东西? words是一个字符串列表。我发现我需要经常这样做,并且在使用几个不同的样本大小进行计时之后,第一种方法似乎始终更快,尽管在表面价值上似乎效率较低(len被调用两次的冗余似乎无关紧要 - 在这种形式的C代码?)。

4

6 回答 6

7

虽然:

max(len(w) for w in words)

确实更容易“阅读” - 你有生成器的开销。

尽管:

len(max(words, key=len))

可以使用内置函数优化掉键,因为len通常是一个非常有效的字符串操作,会更快......

于 2013-02-01T00:30:56.853 回答
5

我认为两者都可以,但我认为除非速度是max(len(w) for w in words)最易读的一个重要考虑因素。

当我看着他们时,我花了更长的时间才弄清楚len(max(words, key=len))在做什么,直到我想得更多,我还是错了。除非有充分的理由不这样做,否则代码应该立即显而易见。

从其他帖子(以及我自己的测试)中可以清楚地看出,可读性较低的帖子速度更快。但这并不像他们中的任何一个都是狗慢的。除非代码在关键路径上,否则不值得担心。

最终,我认为更具可读性的是 Pythonic。

顺便说一句,这是为数不多的 Python 2 在相同任务上明显快于 Python 3 的情况之一。

于 2013-02-01T00:42:26.043 回答
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版本更 Pythonic,原因与 genexp 相同。

它是否与 genexp 版本一样 Pythonic 是有争议的。有些人爱map/ filter/ reduce/等;有些人讨厌他们;我个人的感觉是,当您尝试映射一个已经存在并且具有好名字的函数时(也就是说,您不需要lambdapartial向上的东西),map更好,但是 YMMV(特别是如果您的名字是 Guido) .

最后一点:

len 被调用两次的冗余似乎无关紧要 - 这种形式的 C 代码中会发生更多情况吗?

想一想:你已经调用了lenN 次。与您必须做的任何事情相比,将其称为N+1时间几乎不可能有所作为N,除非您有少量字符串。

于 2013-02-01T00:51:06.067 回答
1

我会说

len(max(x, key=len))

看起来相当不错,因为您使用内置 ( ) 的关键字参数 ( key) 和max内置 ( len)。所以基本上max(x, key=len)你几乎可以得到答案。但你的代码变体对我来说都不是特别不符合 Python 的。

于 2013-02-01T00:28:03.683 回答
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
于 2013-02-01T00:35:34.043 回答
-1

我知道现在已经一年了,但无论如何,我想出了这个:

'''编写一个函数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)
于 2014-08-30T03:28:48.123 回答