【问题标题】:Find second largest element in list with repeated elements查找具有重复元素的列表中的第二大元素
【发布时间】:2013-10-16 20:08:43
【问题描述】:

我有一个列表,其中设置了几个非常大的值来区分这些索引,它看起来像这样:

a = [1.3, 2.1, 9999., 5., 3.7 ,6.6, 9999., 7.4, 9999., 3.5, 7, 1.2, 9999.]

我需要以最有效的方式(我的列表可以变得很大)

在这个问题Retrieve the two highest item from a list containing 100,000 integers 中提到了heapq.nlargest 函数,但由于我有多个值9999.,所以它不起作用。

【问题讨论】:

  • 第二大,还是最大不等于 9999 ?
  • 最大不等于 9999。我称它为 第二大,因为我认为所有这些 9999 值都是一样的,但也许这有点令人困惑。我应该编辑问题的名称吗?

标签: python list


【解决方案1】:

这是另一种方法:

>>> a = [1.3, 2.1, 9999., 5., 3.7 ,6.6, 9999., 7.4, 9999., 3.5, 7, 1.2, 9999.]
>>> sorted(set(a))[-2]
7.4
>>>

而且,不管你信不信,它实际上比公认的解决方案要快得多:

>>> from timeit import timeit
>>> timeit("a=range(10000000);print sorted(set(a))[-2]", number=10)
9999998
9999998
9999998
9999998
9999998
9999998
9999998
9999998
9999998
9999998
34.327036257401424
>>> # This is NPE's answer
>>> timeit("a=range(10000000);maxa = max(a);print max(val for val in a if val != maxa)", number=10)
9999998
9999998
9999998
9999998
9999998
9999998
9999998
9999998
9999998
9999998
53.22811809880869
>>>

以上是一个运行 10 次并使用包含 10,000,000 个项目的列表的测试。除非我的测试有缺陷(我认为没有),否则我给出的解决方案显然要快得多。

【讨论】:

  • 我不敢相信!但它也对我有用。暂时+1!也许range() 给出了一个已经排序的列表,因此不“公平”?
  • 我也尝试了a=[ i%10 for i in range(1000000) ]; 并得到了相同的结果。令人着迷。
  • @AaronMcDaid - 无论列表是否已排序,Python 仍然需要对其进行检查。毕竟,计算机怎么知道它的排序?我想我说计算机不能,所以无论如何它都会对列表进行排序。另外,我也给了 NPE 的答案一个排序列表,所以一切都是公平的。
  • 通常人们说快速排序的复杂度为 N log N,但这只是平均水平。如果数据以非常糟糕的方式排序,则复杂度会跃升至 N^2。或者它可以是 O(N) 的数据已经按照正确的顺序(但这取决于)。所以,是的,正如你所说,它无论如何都必须对其进行排序。问题在于,在您设计的数据集上完成排序的速度可能比在随机数据上快得多。
  • 太好了,我已将接受的答案更改为这个答案,因为性能是问题的中心,而这是表现最好的答案。谢谢大家!
【解决方案2】:
>>> max(val for val in a if val != 9999)
7.4

这具有O(n) 时间复杂度。

如果9999 不固定,您可以通过使用max(a) 而不是9999 来概括这一点:

>>> maxa = max(a)
>>> max(val for val in a if val != maxa)
7.4

(虽然我怀疑这不是你想要的。)

【讨论】:

  • if val != max(a)
  • 请确保您在外面致电max(a) 获取发电机。
【解决方案3】:
a = set([1.3, 2.1, 9999., 5., 3.7 ,6.6, 9999., 7.4, 9999., 3.5, 7, 1.2, 9999.])
a.remove(max(a))
print max(a)

这使用set 来确保我们只处理唯一项目,然后我们删除最大值,这样下次我们调用max 时,我们将得到第二好的最大值。

【讨论】:

    【解决方案4】:

    如果你想使用 numpy,你可以使用掩码数组来跳过“坏”值:

    import numpy as np
    a = np.array([1.3, 2.1, 9999., 5., 3.7 ,6.6, 9999., 7.4, 9999., 3.5, 7, 1.2, 9999.])
    ma = np.ma.masked_values(a, 9999., copy=False)
    ma.max()
    7.4
    

    您可以轻松地将排除项添加到您的掩码中:

    ma = np.ma.masked_values(ma, 7.4, copy=False)
    ma.max()
    7.0
    ma.mask[ma>=5]=True   
    ma.max()
    3.7
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-03
      • 1970-01-01
      • 1970-01-01
      • 2016-10-04
      • 1970-01-01
      • 2019-07-30
      相关资源
      最近更新 更多