我想得到列表中最小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
返回列表中最小值的第一个索引,但我不知道如何在多次出现时返回最小值的所有索引。
答案 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