Python:在浮动列表中查找最小项目的索引[重复]

Posted

技术标签:

【中文标题】Python:在浮动列表中查找最小项目的索引[重复]【英文标题】:Python: Find index of minimum item in list of floats [duplicate] 【发布时间】:2012-10-29 08:28:34 【问题描述】:

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

minIndex = myList.index(min(myList))

但是,对于浮点数列表,我会收到以下错误,我认为是因为浮点数相等比较相当不确定。

ValueError: 0.13417985135 is not in list

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

【问题讨论】:

这应该适用于整数和浮点数......你能告诉我们一个浮点数不起作用的具体例子吗? 浮点数的位数是有限的,所以比较不会有问题。 浮点比较不是不确定的。比较两个浮点数是否相等当且仅当数字相等时才返回真,在任何没有严重破坏的浮点实现中。一个潜在的问题是列表中的 NaN。在这种情况下,最小值运算符可以返回 NaN,但相等比较会报告 NaN 不等于任何值(包括它自己),这可能会导致例程返回最小值索引的问题。如果列表中没有 NaN,则表明还有一些其他问题尚未在任何答案中解决。 这个问题被标记为重复,但这比 imo 顶部横幅上链接的问题 ymmv 有更好的答案。 【参考方案1】:

我会使用:

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

那么val 将是最小值,idx 将是它的索引。

【讨论】:

+1。这比首先得到最小值然后找到它更有效,更简单(一旦你理解了生成器表达式)。另外,它自动适用于可以用< 排序但不能与== 比较的值(我不认为实际上是OP的问题,但他似乎是这样认为的)。 @abarnert -- 谨慎地对效率做出宏大的声明。这是一个大小相关的问题。考虑一下:python -m timeit -s 'my_list = range(1000)[::-1]' 'my_list.index(min(my_list))'——每个循环 96.8 微秒(并精心设计为最坏的情况)。 python -m timeit -s 'my_list = range(1000)' 'min((val, idx) for (idx, val) in enumerate(my_list))' -- 每个循环 345 微秒 -- 对于大小为 1000 的列表,速度要慢 3.5 倍。但它确实有其他优点 -- 例如,它适用于任何可迭代对象。 @mgilson:当我运行完全相同的测试时,我得到 333us 与 187us,或者快 2 倍而不是慢 3.5 倍……(Python 3.3 与 2.7?64 位与 32 位?谁知道?)同时,index 解决方案也适用于任何可迭代对象;您只需输入list(myiter)。在某些情况下,空间损失可能是不可接受的,但时间损失可能不会(因为您已经在列表中进行 N 次遍历)。 @abarnert -- 我在 OS-X 10.5.8(因此是 32 位)上使用 py27。在 python3 上,range 没有给出列表……也许这可能是个问题? (虽然它对我来说运行得更快:) -- 83.4 usec @fractal_7 你可以用itertools.groupby做一些技巧:_, minimums = next(groupby(sorted((val, idx) for (idx, val) in enumerate(my_list)), key=lambda x: x[0]), [])。但这并不那么漂亮,所以那时我可能会编写一个函数来以更好的方式做到这一点。【参考方案2】:

您实际上是在扫描列表一次以找到最小值,然后再次扫描它以找到索引,您可以一次性完成:

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

【讨论】:

啊,整洁。我没有意识到min(大概是max)接受key 参数。 +1! @DavidWolever Yup minmax(如 sortsorted)带一个键比较功能 - 非常有用 - 只是希望 set 以它为例 对于大小为 1000 的列表,仍然不如 OP 的代码快:) 这将如何处理重复的最小值? @Borealis 为什么?它模拟 list.index 的行为(这是 OP 正在尝试做的),它找到 first 最小值的索引...你能描述一下你认为这个答案需要考虑的内容吗帐号?【参考方案3】:

对 numpy 数组使用 argmin 方法。

import numpy as np
np.argmin(myList)

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

【讨论】:

【参考方案4】:

我认为值得在这里放一些时间以获得一些观点。

在 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

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

请注意,我故意将最小的项目放在列表的最后,以使.index 尽可能慢。看看迭代一次的答案会与我们这里的迭代两次答案竞争在多少 N 时会很有趣。

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

【讨论】:

+1 表示最后一段。特别是因为OP专门要求最优雅的方式,而不是最快的方式。还值得一提的是,如果 OP 关于floats 不是自平等的(即使我不认为这是一个实际问题......)是正确的,那么前两个解决方案仍然有效。

以上是关于Python:在浮动列表中查找最小项目的索引[重复]的主要内容,如果未能解决你的问题,请参考以下文章

在列表列表中查找最小值[重复]

查找列表的“最佳”项并在python中打印第一个实例的索引位置[重复]

Python 列表查找,如何在列表中查找项目或者元素索引翻译

如何查找相同项目的列表索引[重复]

python-列表排重并列出重复项和重复项最小索引

在 Python 中查找最小值或最大值的值的索引