如何在Python中找到列表中前N个最大值的位置?

11
我将尝试从列表中找出N个最大的值,然后打印出它们在列表中的位置。
如果我只关注最大值,代码如下:
>>>>fr = [8,4,1,1,12]
>>>>print fr.index(max(fr))
4

然而,我的目标是获得类似于当n=3时的输出:4,0,1。这里的0表示第二大值的位置。请记住,我对数值本身不感兴趣,只关注它们的位置!

1
输入中的 0 在哪里? - thefourtheye
0 表示第二大值的位置...请记住,我不关心该值,而是它们的位 置!:-) 谢谢! - user3604362
1
@thefourtheye 列表中第二大的数字的位置是 0 - KBN
6个回答

24
使用 heapq.nlargest,并且将key设置为fr.__getitem__
>>> import heapq
>>> fr = [8,4,1,1,12]
>>> heapq.nlargest(3, xrange(len(fr)), key=fr.__getitem__)
[4, 0, 1]

如果您想获取值本身,则:

>>> heapq.nlargest(3, fr)
[12, 8, 4]

太好了!那正是我需要的!你介意解释一下它是如何工作的吗?谢谢! - user3604362
1
它根据键即fr中这些索引处的值对索引xrange(len(fr))进行排序,并返回前3个最大值。它并不是真正的排序,而是使用heapq算法获取最大的项目。 - Ashwini Chaudhary

8
另一种方法是:
[fr.index(x) for x in sorted(fr, reverse=True)[:3]]

当我们比较它们的速度时...
import heapq

fr = [8, 4, 1, 1, 12]


def method_one():
    for i in xrange(10000):
        res = [fr.index(x) for x in sorted(fr, reverse=True)[:3]]


def method_two():
    for i in xrange(10000):
        heapq.nlargest(3, xrange(len(fr)), key=fr.__getitem__)


if __name__ == '__main__':
    import timeit

    print timeit.repeat(stmt='method_one()',
                    setup='from __main__ import method_one',
                    number=100)
    print timeit.repeat(stmt='method_two()',
                    setup='from __main__ import method_two',
                    number=100)

我们获得:

[1.1253619194030762, 1.1268768310546875, 1.128382921218872]
[2.5129621028900146, 2.529547929763794, 2.492828130722046]

5
当然,仅有五个项目时是看不到排序的O(n log(n))行为的。唉。 - John La Rooy
我认为它不会停留在最大的三个数字,而是会列出所有索引。 [fr.index(x) for x in sorted(fr, reverse=True)][:3],而这将获取前三个元素。 - KBN
1
请注意,此方法无法处理列表中可能包含重复元素的情况。例如,当 fr = [8,8,1,2,12]n = 4 时,结果为 [4, 0, 0, 3],这可能不是 OP 所要求的。但是,使用堆解决方案可以得到正确的索引 [4,0,1,3] - Anuj Kumar

4

最简单的方法就是这样做

>>> fr = [8,4,1,1,12]
>>> n = 3
>>> result = [fr.index(i) for i in sorted(fr, reverse=True)][:n]
>>> print(result)
[4, 0, 1]

没有库和依赖项。


0
select = 4    
list_val = [5.0, 0, 0, 0, 0, 5.0]
result = [list_val.index(i) for i in sorted(list_val, reverse=True)][:select]
print(result)
    
#expected: [0, 5, 1, 2]
#output: [0, 0, 1, 1]

这种方法并不总是有效。


0
转换列表为NumPy数组并处理它总是很容易的。
import numpy as np

arr = np.array([10, 5, 8, 15, 15, 12])

sorted_indices = np.argsort(arr)[::-1]
largest_indices = sorted_indices[:3]
print(largest_indices)

输出:[4 3 5]

-1

最简单的方法是 -

  In[0]: import numpy as np
    ...: a = [1,4,2,5]
    ...: a.remove(sorted(a)[-1])
    ...: np.argmax(a)
 Out[0]: 1


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接