我有一个列表,其中包含几个非常大的值,用于区分这些索引,它看起来像这样:
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.
,因此无效。
答案 0 :(得分: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个项目的列表。除非我的测试中存在缺陷(我认为没有),否则我给出的解决方案显然要快得多。
答案 1 :(得分: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
(虽然我怀疑这不是你想要的。)
答案 2 :(得分: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
时,我们将保留第二个最佳值号。
答案 3 :(得分: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