Kev*_*fin 395 python list max min
我在列表中使用Python max和min函数来实现minimax算法,我需要max()或者返回的值的索引min().换句话说,我需要知道哪个移动产生了最大值(在第一个玩家的回合)或最小值(第二个玩家)值.
for i in range(9):
newBoard = currentBoard.newBoardWithMove([i / 3, i % 3], player)
if newBoard:
temp = minMax(newBoard, depth + 1, not isMinLevel)
values.append(temp)
if isMinLevel:
return min(values)
else:
return max(values)
Run Code Online (Sandbox Code Playgroud)
我需要能够返回最小值或最大值的实际索引,而不仅仅是值.
gg3*_*349 431
假设您有一个列表values = [3,6,1,5],并且需要最小元素的索引,即index_min = 2在这种情况下.
避免itemgetter()在其他答案中提出的解决方案,而是使用
index_min = min(xrange(len(values)), key=values.__getitem__)
Run Code Online (Sandbox Code Playgroud)
因为它不需要也不需要import operator使用enumerate,并且它总是比使用的解决方案更快(下面的基准)itemgetter().
如果您正在处理numpy数组或者可以numpy作为依赖项,请考虑使用
import numpy as np
index_min = np.argmin(values)
Run Code Online (Sandbox Code Playgroud)
这将比第一个解决方案更快,即使您将其应用于纯Python列表,如果:
numpy数组的内存复制我已经在我的机器上使用python 2.7运行基准测试,用于上面的两个解决方案(蓝色:纯python,第一个解决方案)(红色,numpy解决方案)和基于itemgetter()(黑色,参考解决方案)的标准解决方案.与python 3.5相同的基准测试表明,这些方法与上面提到的python 2.7案例完全相同
too*_*php 344
if isMinLevel:
return values.index(min(values))
else:
return values.index(max(values))
Mat*_*son 320
如果枚举列表中的项目,则可以同时找到最小/最大索引和值,但对列表的原始值执行最小值/最大值.像这样:
import operator
min_index, min_value = min(enumerate(values), key=operator.itemgetter(1))
max_index, max_value = max(enumerate(values), key=operator.itemgetter(1))
Run Code Online (Sandbox Code Playgroud)
这样,列表只会在min(或max)中遍历一次.
小智 108
如果你想在数字列表中找到最大索引(这似乎是你的情况),那么我建议你使用numpy:
import numpy as np
ind = np.argmax(mylist)
Run Code Online (Sandbox Code Playgroud)
Ant*_*t6n 35
可能更简单的解决方案是将值数组转换为值数组,索引对,并取最大值/最小值.这将给出具有最大/最小的最大/最小索引(即,通过首先比较第一元素,然后比较第二元素,如果第一元素相同,则比较对).请注意,没有必要实际创建数组,因为min/max允许生成器作为输入.
values = [3,4,5]
(m,i) = max((v,i) for i,v in enumerate(values))
print (m,i) #(5, 2)
Run Code Online (Sandbox Code Playgroud)
And*_*ndy 28
list=[1.1412, 4.3453, 5.8709, 0.1314]
list.index(min(list))
Run Code Online (Sandbox Code Playgroud)
会给你第一个最小指数.
Nic*_*mer 14
我也对此感兴趣,并使用perfplot(我的宠物项目)比较了一些建议的解决方案.
原来那个numpy的argmin,
numpy.argmin(x)
Run Code Online (Sandbox Code Playgroud)
对于足够大的列表来说,这是最快的方法,即使从输入list到输入的隐式转换也是如此numpy.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,
)
Run Code Online (Sandbox Code Playgroud)
cot*_*ail 10
有两个答案(1、2)包含基准,但由于某种原因,它们都没有包含list.index()在基准中,即使在这些答案之前至少 2 年发布的已接受答案中提出了建议。
list.index()是此页面上给出的最快选项,包括enumerate(涉及它的所有版本),__getitem__并且numpy.argmin.
此外,如果列表具有非唯一的最小值,并且您想要获取出现最小值的所有索引,list.index则 while 循环优于其他选项,例如 numpy 等enumerate。请注意,您可以通过传递起点(这是 的第二个参数list.index)来限制其搜索从特定索引开始,这对于性能至关重要,因为我们不想在 while 的每次迭代中从头开始搜索-环形。
# get the index of the minimum value
my_list = [1, 2, 0, 1]
idxmin = my_list.index(min(my_list))
print(idxmin) # 2
# get all indices where the min value occurs
my_list = [1, 2, 3, 1]
idxmins = []
min_val = min(my_list)
pos = -1
while True:
try:
pos = my_list.index(min_val, pos+1)
# ^^^^^ <---- pick up where we left off in the previous iteration
idxmins.append(pos)
except ValueError:
break
print(idxmins) # [0, 3]
Run Code Online (Sandbox Code Playgroud)
以下基准测试(在 Python 3.11.4 和 numpy 1.25.2 上执行)表明,list.index无论列表的长度如何,它的速度几乎是所有其他选项的两倍。左图还显示,对于长列表,其执行与( 和)getitem相同,这表明gg349和Nico的基准测试已经过时。enumeratenumpy.argmin
右图显示,如果最小值不唯一,并且我们想要找到最小值的所有索引,那么在如上所述的 while 循环中,其性能比涉及或 numpy 的list.index竞争选项要好得多,尤其是对于长列表。enumerate
用于生成上图的代码:
from operator import itemgetter
import numpy as np
import matplotlib.pyplot as plt
import perfplot
def enumerate_1(a):
return min(enumerate(a), key=itemgetter(1))[0]
def np_argmin_1(a):
return np.argmin(a)
def getitem(a):
return min(range(len(a)), key=a.__getitem__)
def list_index_1(a):
return a.index(min(a))
def enumerate_2(a):
min_val = min(a)
return [i for i, v in enumerate(a) if v == min_val]
def np_argmin_2(a):
arr = np.array(a)
return np.arange(len(a))[arr==arr.min()]
def list_index_2(a):
result = []
min_val = min(a)
pos = -1
while True:
try:
pos = a.index(min_val, pos+1)
result.append(pos)
except ValueError:
break
return result
kernels_list = [[enumerate_1, list_index_1, np_argmin_1, getitem],
[enumerate_2, list_index_2, np_argmin_2]]
n_range = [2**k for k in range(1, 20)]
su = lambda n: list(range(n, 0, -1))
titles = ['Get index of a unique min value',
'Get indices of a non-unique min value']
labels = ['enumerate', 'list_index', 'np_argmin', 'getitem']
xlabel = 'List length'
fig, axs = plt.subplots(1, 2, figsize=(12, 5), facecolor='white', dpi=60)
for ax, ks, t in zip(axs, kernels_list, titles):
plt.sca(ax)
perfplot.plot(ks, n_range, su, None, labels, xlabel, t, relative_to=1)
ax.xaxis.set_tick_params(labelsize=13)
plt.setp(axs, ylim=(0, 5), yticks=range(1, 6),
xlim=(1, 1100000), xscale='log', xticks=[1, 100, 10000, 1000000]);
fig.tight_layout();
fig.savefig('benchmark.png', dpi=60);
Run Code Online (Sandbox Code Playgroud)
获得最大值后,请尝试以下操作:
max_val = max(list)
index_max = list.index(max_val)
Run Code Online (Sandbox Code Playgroud)
比许多选项简单得多.
小智 8
使用numpy数组和argmax()函数
a=np.array([1,2,3])
b=np.argmax(a)
print(b) #2
Run Code Online (Sandbox Code Playgroud)
我认为最好的办法是将列表转换为a numpy array并使用以下功能:
a = np.array(list)
idx = np.argmax(a)
Run Code Online (Sandbox Code Playgroud)
小智 6
我认为上面的答案解决了您的问题,但我想我会分享一种方法,该方法可以为您提供最小值以及所有出现在其中的索引。
minval = min(mylist)
ind = [i for i, v in enumerate(mylist) if v == minval]
Run Code Online (Sandbox Code Playgroud)
这两次通过了列表,但仍然非常快。但是,这比找到最小值的第一次遇到的索引要慢一些。因此,如果您仅需要一个最小值,请使用Matt Anderson的解决方案,如果您需要全部解决方案,请使用此解决方案。
使用numpy模块的函数numpy.where
import numpy as n
x = n.array((3,3,4,7,4,56,65,1))
Run Code Online (Sandbox Code Playgroud)
对于最小值索引:
idx = n.where(x==x.min())[0]
Run Code Online (Sandbox Code Playgroud)
对于最大值的索引:
idx = n.where(x==x.max())[0]
Run Code Online (Sandbox Code Playgroud)
实际上,这个功能要强大得多.您可以构造各种布尔运算对于3到60之间的值索引:
idx = n.where((x>3)&(x<60))[0]
idx
array([2, 3, 4, 5])
x[idx]
array([ 4, 7, 4, 56])
Run Code Online (Sandbox Code Playgroud)
使用内置enumerate()和max()函数以及函数的可选key参数max()和简单的lambda表达式,就可以轻松实现:
theList = [1, 5, 10]
maxIndex, maxValue = max(enumerate(theList), key=lambda v: v[1])
# => (2, 10)
Run Code Online (Sandbox Code Playgroud)
在文档中max()说,该key参数需要一个类似于函数中的list.sort()函数。另请参阅“ 排序方法”。
的工作原理相同min()。顺便说一句,它返回第一个最大值/最小值。
您可以将 lambda 作为key=参数传递给max()/ min():
max_index = max(range(len(my_list)), key=lambda index: my_list[index])
Run Code Online (Sandbox Code Playgroud)
假设您有一个列表,例如:
a = [9,8,7]
Run Code Online (Sandbox Code Playgroud)
以下两种方法是获取具有最小元素及其索引的元组的非常紧凑的方法。两者都需要相似的时间来处理。我更喜欢 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)
Run Code Online (Sandbox Code Playgroud)
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)
Run Code Online (Sandbox Code Playgroud)