Python:查找浮点列表中最小项的索引

tho*_*ate 41 python floating-point list minimum floating-point-precision

如何在Python浮动列表中找到最小项的索引?如果它们是整数,我只会这样做:

minIndex = myList.index(min(myList))
Run Code Online (Sandbox Code Playgroud)

但是,对于浮点数列表,我得到以下错误,我假设因为浮点相等比较相当不确定.

ValueError: 0.13417985135 is not in list
Run Code Online (Sandbox Code Playgroud)

现在,我知道我可以简单地滚动列表并比较每个项目,看它是<(min + 0.0000000000001)和>(min - 0.0000000000001),但这有点混乱.是否有更优雅(最好是内置)的方法来查找浮动列表中最小项的索引?

Dav*_*ver 69

我会用:

val, idx = min((val, idx) for (idx, val) in enumerate(my_list))
Run Code Online (Sandbox Code Playgroud)

然后val将是最小值idx并将是其索引.


Jon*_*nts 56

您有效地扫描列表一次以找到最小值,然后再次扫描以找到索引,您可以一次性完成这两项操作:

from operator import itemgetter
min(enumerate(a), key=itemgetter(1))[0] 
Run Code Online (Sandbox Code Playgroud)

  • @Borealis 为什么?它模拟了`list.index`(这是OP试图做的)的行为,它找到了*第一个*最小值的索引......你能描述一下你认为这个答案需要考虑什么吗? (2认同)

小智 24

将argmin方法用于numpy数组.

import numpy as np
np.argmin(myList)
Run Code Online (Sandbox Code Playgroud)

但是,它不是最快的方法:它比我在计算机上的OP的答案慢3倍.它可能是最简洁的一个.


mgi*_*son 14

我认为值得在这里提出一些时间来看待一些观点.

使用python2.7在OS-X 10.5.8上完成所有计时

约翰克莱门特的答案:

python -m timeit -s 'my_list = range(1000)[::-1]; from operator import itemgetter' 'min(enumerate(my_list),key=itemgetter(1))'
1000 loops, best of 3: 239 usec per loop    
Run Code Online (Sandbox Code Playgroud)

David Wolever的回答:

python -m timeit -s 'my_list = range(1000)[::-1]' 'min((val, idx) for (idx, val) in enumerate(my_list))
1000 loops, best of 3: 345 usec per loop
Run Code Online (Sandbox Code Playgroud)

OP的答案:

python -m timeit -s 'my_list = range(1000)[::-1]' 'my_list.index(min(my_list))'
10000 loops, best of 3: 96.8 usec per loop
Run Code Online (Sandbox Code Playgroud)

请注意,我有意将最小的项目放在列表的最后,以.index尽可能慢.有趣的是,一旦答案将与我们在这里的迭代两次答案竞争变得具有竞争力.

当然,速度并非一切,而且大多数时候,它甚至不值得担心...选择最容易阅读的那个,除非这是您的代码中的性能瓶颈(然后在典型的现实世界中进行分析)数据 - 最好是在您的目标机器上).

  • 最后一段+1.特别是因为OP特别要求最优雅的方式,而不是最快的.值得一提的是,如果OP是正确的,即浮动不是自相等的(即使我不认为这是一个实际的问题......),前两个解决方案仍然可行. (3认同)