【问题标题】:Length of longest word in a list列表中最长单词的长度
【发布时间】:2013-01-16 06:10:57
【问题描述】:

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

len(max(words, key=len))

或者:

max(len(w) for w in words)

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

【问题讨论】:

  • @isedev 会给出单词,而不是单词的长度
  • 我个人更喜欢后者,看起来更漂亮
  • len(max(words, key=len)) 很好,因为它可以作为 哦,我忘了 max 将密钥作为参数。 提醒湿器。
  • 一般而言,python 与英语配合得很好,所以如果你能读懂它并且很清楚,那么你可能很好。 1. len max 个单词,或 2. max len 个单词。
  • @monkut:但第一个更像是“len max of words by len”。

标签: python string performance list coding-style


【解决方案1】:

虽然:

max(len(w) for w in words)

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

同时:

len(max(words, key=len))

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

【讨论】:

  • 话虽如此 - 我不能说哪个更“Pythonic” - 我喜欢两者,但对于不熟悉使用 maxkey 的人来说,也许前者会是更容易理解
【解决方案2】:

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

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

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

归根结底,我认为更具可读性的是 Pythonic。

顺便说一句,这是少数情况下 Python 2 在执行相同任务时明显比 Python 3 快的情况之一。

【讨论】:

  • 在我的测试中,3.3.0 在我能想到的每个版本中都击败了 2.7.2。 (请参阅我的答案以获得明显的答案。)
  • 更新:实际上,如果我同时在 32 位模式下运行它们,3.3.0 会明显变慢。但是在 32 位 3.2 或 3.3 中,几乎所有东西都显得很慢,至少在 Mac 上是这样,所以我认为这种情况没有什么特别之处。
  • @abarnert:很有趣。我在 Linux 系统上以 64 位模式运行它们。一个是 Python 2.7.3,另一个是 3.3.0。我使用/usr/share/dict/words 作为单词列表。我的速度是 88 毫秒和 66 毫秒。也许是我选择了一个很长的单词列表才有所作为。
  • @Omnifarous:使用 70000 个字而不是 700 个字,我得到几乎完全相同的性能数字乘以 100。基本上,64 位 3.3 比 64 位 2.7 快 8-14%,但 32 -bit 3.3 比 32-bit 2.7 慢 0-10%(并且 32-bit 和 64-bit 2.7 相差在 2% 以内)。 (但是,正如您所料,PyPy 在 70000 上的表现似乎比 700 好得多……我没有将它包含在我的答案中,因为我正在测试的机器没有用于 pypy 的 ipython。)
【解决方案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 代码中会发生更多情况吗?

这样想:你已经给len打了N次电话了。与 N 次您必须做的任何事情相比,将其称为 N+1 次几乎不可能有所作为,除非您有 tiny 数量的 huge 字符串.

【讨论】:

  • max(map(len, words)) 也非常易读和明显。所以它得到了我的投票。
  • @Omnifarious:这对我和你来说都是易读且显而易见的……但也许不是每个人。我添加了一段关于此的内容。
【解决方案4】:

我会说

len(max(x, key=len))

看起来相当不错,因为您使用了内置 (max) 的关键字参数 (key) 和内置 (len)。所以基本上max(x, key=len) 几乎可以为您提供答案。但是在我看来,您的所有代码变体都不是 Python 的。

【讨论】:

  • 但是为什么?有什么原因吗?
  • @A.R.S.:添加了一个简短的,嗯,......主观原因。
【解决方案5】:

仅供参考,请使用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

【讨论】:

  • 随着列表越长,差异越大。
【解决方案6】:

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

'''写一个函数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)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-29
    • 2019-04-28
    • 1970-01-01
    • 2020-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-28
    相关资源
    最近更新 更多