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

Python:在浮动列表中查找最小项的索引,python,list,floating-point,minimum,floating-point-precision,Python,List,Floating Point,Minimum,Floating Point Precision,如何在Python浮动列表中找到最小项的索引?如果它们是整数,我只需要做: minIndex = myList.index(min(myList)) 然而,对于一个浮点列表,我得到了以下错误,我假设,因为浮点相等比较是相当不确定的 ValueError: 0.13417985135 is not in list 现在,我知道我可以简单地滚动列表并比较每个项目,看看它是否是(min-0.0000000000001),但这有点混乱。是否有更优雅(最好是内置)的方法来查找浮动列表中最小项的索引?我

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

minIndex = myList.index(min(myList))
然而,对于一个浮点列表,我得到了以下错误,我假设,因为浮点相等比较是相当不确定的

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

我会使用:

val, idx = min((val, idx) for (idx, val) in enumerate(my_list))

然后,
val
将是最小值,
idx
将是其索引。

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

from operator import itemgetter
min(enumerate(a), key=itemgetter(1))[0] 

我认为,从某种角度来看,在这里列出一些时间安排是值得的

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

约翰·克莱门特的回答是:

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    
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
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
David Wolever的回答是:

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    
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
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
OP的答复:

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    
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
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
请注意,我有意将最小的项放在列表的最后,以使
.index
尽可能慢。有趣的是,看看迭代一次答案与我们这里的迭代二次答案在什么程度上具有竞争性


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

对numpy阵列使用argmin方法

import numpy as np
np.argmin(myList)

然而,这并不是最快的方法:它比我电脑上OP的答案慢3倍。不过,这可能是最简洁的一个。

这应该适用于整数和浮点数。。。你能给我们看一个浮点数不起作用的具体例子吗?浮点数中有有限多个位,所以比较不会有问题。浮点数比较是不确定的。在任何没有严重损坏的浮点实现中,比较两个浮点数是否相等,当且仅当两个浮点数相等时,返回true。一个潜在的问题是列表中的NAN。在这种情况下,最小运算符可以返回NaN,但相等比较会报告NaN不等于任何值(包括其本身),这可能会导致例程返回最小值的索引时出现问题。如果列表中没有NaN,则表明其他问题尚未在任何答案中解决。此问题标记为重复,但此问题的答案比顶部imo横幅上链接的ymmv+1更好。这比先得到最小值,然后再找到它更有效,也更简单(一旦您理解了生成器表达式)。此外,它还可以自动为那些可以通过
@abarnert订购的值工作——小心地对效率大肆宣扬。这是一个大小相关的问题。考虑:
python-m timeit-s'my_list=range(1000)[::-1]''my_list.index(min(my_list))'
--96.8usec/循环(精心设计为最坏情况)
python-m timeit-s'my_list=range(1000)'min((val,idx)for(idx,val)in enumerate(my_list))”
--345 usec/循环--对于大小为1000的列表,速度要慢3.5倍。不过它还有其他的优点——例如,它适用于任何一个iterable。@mgilson:当我运行完全相同的测试时,我得到333us比187us快了2倍,而不是慢了3.5倍……(Python 3.3比2.7?64位比32位?谁知道呢?)同时,
索引
解决方案也适用于任何一个iterable;您只需输入一个
列表(myiter)
。在某些情况下,空间惩罚可能是不可接受的,但时间惩罚可能不会(因为您已经在列表中进行了N次遍历)。@abarnert——我正在OS-X 10.5.8上使用py27(因此为32位)。在python3上,
range
不提供列表。。。也许这是个问题?(尽管对我来说跑得更快:)--83.4usec@fractal_7您可以使用
itertools.groupby
,minimums=next(groupby(已排序((val,idx)for(idx,val))for enumerate(my_list)),key=lambda x:x[0]),[])
。但这并没有那么漂亮,所以在这一点上,我可能会编写一个函数,以更好的方式实现这一点。我没有意识到
min
(大概是
max
)接受
参数+1!@DavidWolever Yup
min
max
(如
sort
sorted
)使用一个键比较函数-非常有用-只希望
set
将其作为一个实例,直到没有OP的代码处理大小为1000的列表时那么快:)这将如何处理重复的最小值?@Borealis为什么?它模拟了
list.index
(OP正试图做的事情)的行为,该行为找到第一个最小值的索引。。。你能描述一下你认为这个答案需要考虑什么吗?最后一段+1。特别是因为OP特别要求的是最优雅的方式,而不是最快的方式。还值得一提的是,如果OP关于
float
s不自平等的观点是正确的(尽管我认为这不是一个实际问题…),那么前两个解决方案仍然有效。