获取Python中列表的最小N个元素的索引

时间:2015-04-16 14:24:38

标签: python arrays list

我想得到列表中最小N个元素的索引。如果我可以在另一个列表中获得该输出,那将是很好的。

例如:

[1, 1, 10, 5, 3, 5]
output = [0, 1]

[10, 5, 12, 5, 0, 10]
output = [4]

[9, 2, 8, 2, 3, 4, 2]
output = [1, 3, 6]

[10, 10, 10, 10, 10, 10]
output = [0, 1, 2, 3, 4, 5]

我知道.index返回列表中最小值的第一个索引,但我不知道如何在多次出现时返回最小值的所有索引。

2 个答案:

答案 0 :(得分:7)

>>> L = [9, 2, 8, 2, 3, 4, 2]
>>> minL = min(L)
>>> [i for i, x in enumerate(L) if x == minL]
[1, 3, 6]

目前,其他解决方案将在迭代期间调用min,从而导致较差且不必要的 O(n ^ 2)复杂性。


编辑Kasra:天真解决方案n ^ 2复杂性的证据:

>>> L1000 = [randint(0, 100) for _ in xrange(1000)]
>>> L2000 = [randint(0, 100) for _ in xrange(2000)]
>>> L3000 = [randint(0, 100) for _ in xrange(3000)]
>>> L4000 = [randint(0, 100) for _ in xrange(4000)]
>>> L5000 = [randint(0, 100) for _ in xrange(5000)]
>>> timeit [i for i, x in enumerate(L1000) if x == min(L1000)]
10 loops, best of 3: 18.8 ms per loop
>>> timeit [i for i, x in enumerate(L2000) if x == min(L2000)]
10 loops, best of 3: 73.6 ms per loop
>>> timeit [i for i, x in enumerate(L3000) if x == min(L3000)]
1 loops, best of 3: 166 ms per loop
>>> timeit [i for i, x in enumerate(L4000) if x == min(L4000)]
1 loops, best of 3: 294 ms per loop
>>> timeit [i for i, x in enumerate(L5000) if x == min(L5000)]
1 loops, best of 3: 457 ms per loop

答案 1 :(得分:4)

您可以使用NumPy以及.where,这对于较大的列表非常有用(更大,数千或更多元素)。

import numpy as np
mylist = [1, 1, 10, 5, 1, 5]
minL = min(mylist)
numparray = np.array(mylist)
print(list( np.where(numparray == minL)[0]))

<强>输出:

[0, 1, 4]

简单基准:

<强> Wim's answer

>>>setup = '''
L = [9, 2, 8, 2, 3, 4, 2] * 5000
minL = min(L)
'''
>>> print (min(timeit.Timer(
            '[i for i, x in enumerate(L) if x == minL]', setup=setup).repeat(7, 1000)))
3.218847516924143

<强> Donkey Kong's answer

>>> setup = '''
import numpy as np
mylist = [9, 2, 8, 2, 3, 4, 2] * 5000
minL = min(mylist)
numparray = np.array(mylist)
'''
>>> print (min(timeit.Timer(
          'list( np.where(numparray == minL)[0])', setup=setup).repeat(7, 1000)))
1.4015787709504366

对于35000元素列表,NumPy解决方案的速度是其两倍多。然而,对于小型列表,Wim的答案就足够了。

此外,还有一个小型基准测试,用于显示在列表理解( 700元素列表)中调用O(n^2) 内部min 的时间复杂度:

>>> setup = '''
L = [9, 2, 8, 2, 3, 4, 2] * 100
'''
>>> print (min(timeit.Timer(
           '[i for i,j in enumerate(L) if j == min(L)]', setup=setup).repeat(7, 1000))) 
7.43799185753