622

我在列表上使用 Pythonmaxmin函数来实现 minimax 算法,我需要max()or返回的值的索引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)

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

4

24 回答 24

604

假设您有一个 list 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数组的内存副本

正如这个基准所指出的: 在此处输入图像描述

我已经使用 python 2.7 在我的机器上针对上述两种解决方案(蓝色:纯 python,第一个解决方案)(红色,numpy 解决方案)和基于itemgetter()(黑色,参考解决方案)的标准解决方案运行了基准测试。与 python 3.5 相同的基准测试表明,这些方法与上面介绍的 python 2.7 案例完全相同

于 2012-08-06T09:43:48.660 回答
552
if is_min_level:
    return values.index(min(values))
else:
    return values.index(max(values))
于 2010-03-18T23:23:08.070 回答
360

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

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

这样,列表只会在最小值(或最大值)内被遍历一次。

于 2010-03-19T00:18:32.087 回答
132

如果您想在数字列表中找到 max 的索引(这似乎是您的情况),那么我建议您使用 numpy:

import numpy as np
ind = np.argmax(mylist)
于 2012-11-23T17:41:42.973 回答
45

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

values = [3,4,5]
(m,i) = max((v,i) for i,v in enumerate(values))
print (m,i) #(5, 2)
于 2012-12-21T11:53:50.750 回答
33
seq=[1.1412, 4.3453, 5.8709, 0.1314]
seq.index(min(seq))

会给你第一个最低指数。

于 2013-09-07T21:30:44.487 回答
21

我认为最好的办法是将列表转换为 anumpy array并使用此功能:

a = np.array(list)
idx = np.argmax(a)
于 2019-01-05T06:24:11.483 回答
16

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

原来numpy的 argmin

numpy.argmin(x)

对于足够大的列表来说,这是最快的方法,即使从输入隐式转换listnumpy.array.

在此处输入图像描述


生成图的代码:

import numpy
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 numpy.argmin(a)


perfplot.show(
    setup=lambda n: numpy.random.rand(n).tolist(),
    kernels=[
        min_enumerate,
        min_enumerate_itemgetter,
        getitem,
        np_argmin,
        ],
    n_range=[2**k for k in range(15)],
    logx=True,
    logy=True,
    )
于 2017-05-23T07:58:59.133 回答
10

我认为上面的答案可以解决您的问题,但我想我会分享一种方法,可以为您提供最小值和最小值出现的所有索引。

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

这通过列表两次,但仍然相当快。然而,它比找到第一次遇到最小值的索引稍慢。因此,如果您只需要其中一个最小值,请使用Matt Anderson的解决方案,如果您需要所有这些,请使用它。

于 2011-04-14T18:22:41.383 回答
10

获得最大值后,试试这个:

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

比许多选项简单得多。

于 2018-01-11T16:57:04.307 回答
8

使用 numpy 数组和 argmax() 函数

 a=np.array([1,2,3])
 b=np.argmax(a)
 print(b) #2
于 2018-01-29T18:07:41.220 回答
7

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

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

在它的文档中max()key参数需要一个函数,就像函数中一样list.sort()。另请参阅排序方法

它对min(). 顺便说一句,它返回第一个最大值/最小值。

于 2016-10-28T09:35:05.953 回答
6

使用 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])
于 2015-04-16T08:29:14.170 回答
6

Pandas 现在有了更温和的解决方案,试试吧:

df[column].idxmax()

于 2020-08-10T09:44:45.887 回答
5

假设您有一个列表,例如:

a = [9,8,7]

以下两种方法是获取具有最小元素及其索引的元组的非常紧凑的方法。两者都需要相似的时间来处理。我更喜欢 zip 方法,但这是我的口味。

拉链法

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)
于 2018-02-26T10:29:40.217 回答
4

为什么要先添加索引然后反转它们?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)
于 2015-03-17T13:45:16.197 回答
4

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

max_index = max( range( len(my_list) ), key = lambda index : my_list[ index ] )
于 2017-01-24T22:41:57.817 回答
4

就那么简单 :

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

index = stuff.index(max(stuff))
于 2017-03-12T19:51:48.600 回答
2

只是对已经说过的内容的一个小补充。 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)在循环之外缓存可能是一个更好的主意。

于 2012-04-06T16:09:02.853 回答
2

如果您不想导入其他模块,一种在列表中查找具有最小值的索引的简单方法:

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]
于 2016-08-09T12:17:54.023 回答
1

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)]
于 2015-09-17T20:42:25.040 回答
1

没有足够高的代表来评论现有答案。

但是对于https://stackoverflow.com/a/11825864/3920439的回答

这适用于整数,但不适用于浮点数组(至少在 python 3.6 中)它会引发TypeError: list indices must be integers or slices, not float

于 2018-02-19T15:41:55.307 回答
1

假设您有以下列表my_list = [1,2,3,4,5,6,7,8,9,10],并且我们知道如果我们这样做max(my_list),它将返回10并将min(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

于 2020-11-14T12:05:59.657 回答
0

那这个呢:

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 的初学者,所以我不知道这个解决方案的计算复杂性。

于 2019-10-12T09:10:33.667 回答