1

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

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

我需要以最有效的方式找到该列表中等于9999.(在上述情况下为7.4)的第二大值(我的列表可能会变得很大)

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

4

4 回答 4

5

这是另一种方法:

>>> 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 个项目的列表。除非我的测试存在缺陷(我认为没有),否则我给出的解决方案显然要快得多。

于 2013-10-16T20:35:53.547 回答
3
>>> 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

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

于 2013-10-16T20:10:36.257 回答
2
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,我们将得到第二好的最大值。

于 2013-10-16T20:11:34.277 回答
0

如果你想使用 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
于 2013-10-16T23:07:32.637 回答