Python:如何找到最小元素的最后一个索引?

8
例如 [1,2,3,4,1,2]
最小的元素是 1,但它最后一次出现在索引位置 4。
6个回答

13
>>> values = [1,2,3,4,1,2]
>>> -min((x, -i) for i, x in enumerate(values))[1]
4

不对原始列表进行修改,适用于任意可迭代对象,并且仅需要一次遍历。

这将创建一个元组的可迭代对象,其中第一个值是来自列表的原始元素,第二个元素是索引的取反。在此元组的可迭代对象中查找最小值时,首先比较值,然后是索引,因此您将得到一个元组(min_value, lowest_negative_index)。通过再次取反该元组的第二个元素,您将获得最小值的最高索引。

以下是另一种非常相似的版本,但使用了min()的键函数:

>>> min(range(len(values)), key=lambda i: (values[i], -i))
4

请注意,此版本仅适用于序列(列表、元组、字符串等)。


我认为你的第二个解决方案可以受益于不在每次比较时分配元组:min(range(len(values)), key=lambda i: values[i]-i) - ovgolovin
@ovgolovin 有趣的时间结果,我有点惊讶我的版本比其他一些版本慢了一点。枚举或生成表达式必须有更多的开销,这是我没有意识到的。此外,你对第二个解决方案的修改并不总是会得到正确的答案,请考虑列表 [0, 2, 2, 2, 1]。即使它不是列表中最小的,你也会得到 4 作为结果。 - Andrew Clark
我认为速度问题归结于元组的创建。请参阅我最近关于此主题的问题(非常不明显):https://dev59.com/CnTYa4cB1Zd3GeqPunGl - ovgolovin

3
a = [1,2,3,4,1,2]

a.reverse()
print len(a) - a.index(min(a)) - 1

评论后更新:

副作用可以通过再次反转来消除(但这当然很低效)。

a.reverse()

3
这也会有一个副作用,即将他的列表反转。 - Stephan

3

len(list_) - list_[::-1].index(min(list_)) - 1

这段代码的意思是:先求出列表的长度,然后用倒序的列表中最小值的索引减去该值在正序列表中的索引,并将结果减1。

该代码通常用于寻找列表中最小值的索引。


2

虽然我在Python方面是初学者,但这个方法也能正常工作,只是idx会保存最小元素的最后一个索引。我认为M.Keijzers的方法是最好的。

array = [1,2,3,4,1,2]
min_val = min(array) 
for i in range(len(array)):
    if array[i] == min_val:
        idx = i

print idx

2
>>> from operator import itemgetter
>>> from itertools import izip,count
>>> min(izip(count(len(L)-1,-1), reversed(L)), key=itemgetter(1))[0]
4

说明

reversed 返回迭代器,它可以遍历原始列表而不创建临时列表:

>>> reversed(L)
<listreverseiterator object at 0x00E823B0>

izipcount是惰性的,似乎没有字节码执行,所以我希望这个解决方案非常快,并且只需要一行代码。


时间比较

http://ideone.com/ZQuge3

尽管使用index的解决方案需要对列表进行两次遍历,但它们被证明是最快的。其他解决方案在每次迭代中都会创建辅助元组,并且我认为这就是这些解决方案较慢的原因。即使akson128的解决方案调用了字节码执行,但它仍然更快(因为它不必创建元组)。


2
len(myList)-1 - myList[::-1].index(min(list))

这里使用了切片符号list[::-1]来返回一个反转列表的浅拷贝,以避免更改原始列表,然后在该列表中搜索最小值。

>>>myList = [1,2,3,4,1,2]
>>>len(myList)-1 - myList[::-1].index(min(list))
4

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接