使用max()/min()在列表上获取返回的max或min项的索引

我正在使用Python的maxmin函数对列表进行极大极小算法,我需要max()min()返回值的索引。换句话说,我需要知道哪一步棋产生了最大(第一个玩家的回合)或最小(第二个玩家的回合)值。

for i in range(9):
new_board = current_board.new_board_with_move([i / 3, i % 3], player)


if new_board:
temp = min_max(new_board, depth + 1, not is_min_level)
values.append(temp)


if is_min_level:
return min(values)
else:
return max(values)

我需要能够返回最小值或最大值的实际索引,而不仅仅是值。

1377080 次浏览
if is_min_level:
return values.index(min(values))
else:
return values.index(max(values))

如果枚举列表中的项目,可以同时找到min/max索引和值,但对列表的原始值执行min/max。像这样:

import operator
min_index, min_value = min(enumerate(values), key=operator.itemgetter(1))
max_index, max_value = max(enumerate(values), key=operator.itemgetter(1))

这样,对于min(或max),列表将只遍历一次。

我认为上面的答案解决了你的问题,但我想我要分享一个方法,给你最小值和最小值出现的所有指标。

minval = min(mylist)
ind = [i for i, v in enumerate(mylist) if v == minval]

它两次通过列表,但仍然相当快。然而,它比找到第一次遇到最小值的指数略慢。所以如果你只需要其中一个极小值,使用马特•安德森的解决方案,如果你需要所有的,使用这个。

只是对已经说过的内容的一个小小的补充。 values.index(min(values))似乎返回min的最小下标。下面得到最大下标:

    values.reverse()
(values.index(min(values)) + len(values) - 1) % len(values)
values.reverse()

如果原地反转的副作用不重要,最后一行可以省略。

遍历所有发生的事件

    indices = []
i = -1
for _ in range(values.count(min(values))):
i = values[i + 1:].index(min(values)) + i + 1
indices.append(i)

为了简洁起见。在循环之外缓存min(values), values.count(min)可能是一个更好的主意。

假设您有一个列表values = [3,6,1,5],并且需要最小元素的索引,在本例中为index_min = 2

避免使用其他答案中给出的itemgetter()的解决方案,而是使用

index_min = min(range(len(values)), key=values.__getitem__)

因为它不需要import operator也不需要使用enumerate,而且它总是比使用itemgetter()的解决方案更快(下面的基准测试)。

如果您正在处理numpy数组,或者可以负担得起numpy作为依赖项,也可以考虑使用

import numpy as np
index_min = np.argmin(values)

这将比第一个解决方案更快,即使你将它应用于一个纯Python列表,如果:

  • 它比一些元素大(在我的机器上大约2**4个元素)
  • 你可以在内存中从纯列表复制到numpy数组

正如基准所指出的: # EYZ0 < / p > 我已经用python 2.7在我的机器上运行了上面的两个解决方案(蓝色:纯python,第一个解决方案)(红色,numpy解决方案)和基于itemgetter()的标准解决方案(黑色,参考解决方案)的基准测试。 python 3.5的相同基准测试显示,这些方法与上面给出的python 2.7情况完全相同

如果你想在一个数字列表中找到max的下标(这似乎是你的情况),那么我建议你使用numpy:

import numpy as np
ind = np.argmax(mylist)

可能更简单的解决方案是将值数组转换为值、索引对数组,并取其中的最大/最小值。这将给出具有max/min的最大/最小索引(即对的比较首先比较第一个元素,然后比较第二个元素,如果第一个元素相同)。注意,没有必要实际创建数组,因为min/max允许生成器作为输入。

values = [3,4,5]
(m,i) = max((v,i) for i,v in enumerate(values))
print (m,i) #(5, 2)
seq=[1.1412, 4.3453, 5.8709, 0.1314]
seq.index(min(seq))

会给出最小值的第一个指数。

为什么要先添加索引,然后反转它们呢?Enumerate()函数只是zip()函数用法的一个特例。让我们以适当的方式来使用它:

my_indexed_list = zip(my_list, range(len(my_list)))


min_value, min_index = min(my_indexed_list)
max_value, max_index = max(my_indexed_list)

使用numpy模块的函数numpy.where

import numpy as n
x = n.array((3,3,4,7,4,56,65,1))

最小值指数:

idx = n.where(x==x.min())[0]

最大值指数:

idx = n.where(x==x.max())[0]
事实上,这个函数要强大得多。你可以提出各种布尔运算 对于3到60之间的指数:

idx = n.where((x>3)&(x<60))[0]
idx
array([2, 3, 4, 5])
x[idx]
array([ 4,  7,  4, 56])

https://docs.python.org/3/library/functions.html#max

如果有多个最大项,则函数返回遇到的第一个项。这与其他保持排序稳定性的工具(如sorted(iterable, key=keyfunc, reverse=True)[0])是一致的

要获得比第一次遇到的更多信息,请使用sort方法。

import operator


x = [2, 5, 7, 4, 8, 2, 6, 1, 7, 1, 8, 3, 4, 9, 3, 6, 5, 0, 9, 0]


min = False
max = True


min_val_index = sorted( list(zip(x, range(len(x)))), key = operator.itemgetter(0), reverse = min )


max_val_index = sorted( list(zip(x, range(len(x)))), key = operator.itemgetter(0), reverse = max )




min_val_index[0]
>(0, 17)


max_val_index[0]
>(9, 13)


import ittertools


max_val = max_val_index[0][0]


maxes = [n for n in itertools.takewhile(lambda x: x[0] == max_val, max_val_index)]

如果你不想导入额外的模块,找到列表中值最小的索引的简单方法:

min_value = min(values)
indexes_with_min_value = [i for i in range(0,len(values)) if values[i] == min_value]

然后选择第一个例子:

choosen = indexes_with_min_value[0]

使用内置的enumerate()max()函数以及max()函数的可选参数key和一个简单的lambda表达式就可以实现:

theList = [1, 5, 10]
maxIndex, maxValue = max(enumerate(theList), key=lambda v: v[1])
# => (2, 10)

max()的文档中,它说key参数需要一个类似于list.sort()函数的函数。也可以看到如何排序

对于min()也是一样的。顺便说一下,它返回第一个最大/最小值。

只要你知道如何使用lambda和"key"参数,一个简单的解决方案是:

max_index = max( range( len(my_list) ), key = lambda index : my_list[ index ] )

就这么简单:

stuff = [2, 4, 8, 15, 11]


index = stuff.index(max(stuff))

我对此也很感兴趣,并使用perfplot(我的一个爱好项目)比较了一些建议的解决方案。

事实证明

min(range(len(a)), key=a.__getitem__)

是用于小型和大型列表的最快方法。

(在以前的版本中,np.argmin用来吃蛋糕。)

enter image description here


生成图的代码:

import numpy as np
import operator
import perfplot




def min_enumerate(a):
return min(enumerate(a), key=lambda x: x[1])[0]




def min_enumerate_itemgetter(a):
min_index, min_value = min(enumerate(a), key=operator.itemgetter(1))
return min_index




def getitem(a):
return min(range(len(a)), key=a.__getitem__)




def np_argmin(a):
return np.argmin(a)




b = perfplot.bench(
setup=lambda n: np.random.rand(n).tolist(),
kernels=[
min_enumerate,
min_enumerate_itemgetter,
getitem,
np_argmin,
],
n_range=[2**k for k in range(15)],
)
b.show()

在你得到最大值后,试试这个:

max_val = max(list)
index_max = list.index(max_val)

比一大堆选项简单多了。

使用numpy数组和argmax()函数

 a=np.array([1,2,3])
b=np.argmax(a)
print(b) #2

假设你有这样一个列表:

a = [9,8,7]

下面的两个方法是非常紧凑的方法,可以获得具有最小元素及其索引的元组。两者都需要类似的时间来处理。我更喜欢压缩法,但那是我的口味。

邮政法

element, index = min(list(zip(a, range(len(a)))))


min(list(zip(a, range(len(a)))))
(7, 2)


timeit min(list(zip(a, range(len(a)))))
1.36 µs ± 107 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

列举的方法

index, element = min(list(enumerate(a)), key=lambda x:x[1])


min(list(enumerate(a)), key=lambda x:x[1])
(2, 7)


timeit min(list(enumerate(a)), key=lambda x:x[1])
1.45 µs ± 78.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

我认为最好的方法是将列表转换为numpy array并使用这个函数:

a = np.array(list)
idx = np.argmax(a)

那么这个呢:

a=[1,55,2,36,35,34,98,0]
max_index=dict(zip(a,range(len(a))))[max(a)]


它从a中的项创建一个字典作为键,并将它们的索引作为值,因此dict(zip(a,range(len(a))))[max(a)]返回与键max(a)对应的值,这是a中最大值的索引。我是python初学者,所以我不知道这个解决方案的计算复杂性。

熊猫现在有一个更温和的解决方案,试试吧:

# EYZ0

假设你有一个下面的列表my_list = [1,2,3,4,5,6,7,8,9,10],我们知道如果我们做max(my_list),它将返回10min(my_list)将返回1。现在,我们想要获得最大或最小元素的索引,我们可以执行以下操作。

my_list = [1,2,3,4,5,6,7,8,9,10]


max_value = max(my_list) # returns 10
max_value_index = my_list.index(max_value) # retuns 9


#to get an index of minimum value


min_value = min(my_list) # returns 1
min_value_index = my_list.index(min_value) # retuns 0