使用列表中的 max()/min() 获取返回的最大或最小项的索引

2025-01-13 08:52:00
admin
原创
31
摘要:问题描述:我在列表上使用 Python 的max和min函数来实现极小最大算法,我需要max()或返回的值的索引min()。换句话说,我需要知道哪个动作产生了最大值(在第一个玩家的回合)或最小值(第二个玩家)。for i in range(9): new_board = current_board.n...

问题描述:

我在列表上使用 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)

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


解决方案 1:

假设您有一个列表values = [3,6,1,5],并且需要最小元素的索引,index_min = 2在这种情况下为 ie。

避免使用其他答案中提供的解决方案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 案例完全相同

解决方案 2:

用 找到最小值,min()然后用 找到该值的索引.index()

values.index(min(values))

或者最大值:

values.index(max(values))

如果您的列表包含最小值或最大值的重复,这将返回第一个的索引。

解决方案 3:

如果您枚举列表中的项目,但对列表的原始值执行最小/最大操作,则可以同时找到最小/最大索引和值。如下所示:

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

这样,对于最小值(或最大值),列表只会遍历一次。

解决方案 4:

使用 NumPynp.argmin()np.argmax()函数:

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

解决方案 5:

将值数组转换为 (值,索引) 对数组,然后取其中的最大值/最小值。这将返回具有最大值/最小值的最大/最小索引(即,首先比较值,然后如果值相同则比较索引,以此来比较对)。

values = [3, 5, 4, 5]
m, i = max((v, i) for i, v in enumerate(values))
print((m, i))  # (5, 3)

解决方案 6:

我使用perfplot (我的一个业余项目)在 Python 3.11 上对主要答案进行了基准测试,结果表明

values.index(min(values))

是最快的(越低越好):

在此处输入图片描述

除非你的数组已经是一个 numpy 数组。


生成图表的代码:

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)

def index_min(a):
    return a.index(min(a))


b = perfplot.bench(
    setup=lambda n: np.random.rand(n).tolist(),
    kernels=[
        min_enumerate,
        min_enumerate_itemgetter,
        getitem,
        np_argmin,
        index_min,
    ],
    labels = [
        "key=lambda x: x[1]",
        "key=itemgetter(1)",
        "key=.__getitem__",
        "np.argmin()",
        ".index()"
    ],
    xlabel="len(list)",
    n_range=[2**k for k in range(20)],
)
b.show()

解决方案 7:

有两个答案(1、2 )包含基准,但由于某种原因,它们都没有将其纳入基准,尽管这是在这些答案之前至少 2 年前发布的已接受答案中提出的。list.index()

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]

以下基准测试(在 Python 3.11.4 和 numpy 1.25.2 上执行)表明,list.index无论列表长度如何,它的速度几乎是所有其他选项的两倍。左图还显示,对于长列表,其性能与(和)getitem相同,这表明gg349和Nico的基准测试已经过时了。enumerate`numpy.argmin`

右图显示,如果最小值不唯一,而我们想要找到最小值的所有索引,那么list.index上面概述的 while 循环比涉及或 numpy 的竞争选项表现要好得多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);

解决方案 8:

如果您需要最小值的所有索引(因为最小值可能在列表中出现多次):

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

解决方案 9:

获得最大值后,尝试以下操作:

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

比很多选项简单得多。

解决方案 10:

这可以使用内置函数enumerate()以及函数的max()可选参数和简单表达式来实现:key=`max()`lambda

values = [1, 5, 10]
max_index, max_value = max(enumerate(values), key=lambda v: v[1])
# => (2, 10)

在文档中,max()它表示key=参数需要一个类似于list.sort()函数的函数。另请参阅排序方法。

它的工作原理相同min()。顺便说一下,它返回第一个最大/最小值。

解决方案 11:

Pandas 现在有一个更温和的解决方案,尝试一下:

df[column].idxmax()

解决方案 12:

使用 numpy 数组和argmax()函数

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

解决方案 13:

使用 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])

解决方案 14:

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

a = [9,8,7]

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

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)

解决方案 15:

您可以将 lambda 作为key=参数传递给max()/ min()

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

解决方案 16:

为什么要先添加索引,然后再反转它们? 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)

解决方案 17:

就这么简单:

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

index = stuff.index(max(stuff))

解决方案 18:

假设您有一个以下列表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

运行代码片段Hide results展开片段

解决方案 19:

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

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

要获取不仅仅是第一个遇到的结果,请使用排序方法。

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)]

解决方案 20:

只是对已经说过的内容做了一点补充。
values.index(min(values))似乎返回最小的索引。以下获取最大索引:

    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)在循环之外缓存可能是一个更好的主意。

解决方案 21:

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

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]

解决方案 22:

那这个呢:

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

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1043  
  IPD(Integrated Product Development,集成产品开发)是一种系统化的产品开发方法论,旨在通过跨职能团队的协作,优化产品开发的效率和质量。IPD流程强调从市场需求出发,通过并行工程、跨部门协作和阶段性评审,确保产品从概念到上市的每个环节都高效且可控。随着敏捷开发方法的普及,越来越多的企业开始...
华为IPD流程   41  
  随着企业产品开发复杂度的提升以及市场需求的快速变化,传统的产品开发模式逐渐显现出局限性。集成产品开发(IPD)流程与敏捷开发(Agile Development)作为两种主流的开发方法论,分别从系统化管理和快速响应需求的角度为企业提供了解决方案。然而,单独使用其中一种方法往往无法完全满足企业在效率、质量和创新上的多重需...
华为IPD流程   35  
  华为IPD(Integrated Product Development,集成产品开发)流程是华为公司成功的关键因素之一。它不仅帮助华为在技术上实现了快速创新,还通过市场导向确保了产品的商业成功。IPD流程通过整合技术与市场双驱动,实现了从需求定义到产品交付的全生命周期管理。这种模式不仅提高了产品的开发效率,还降低了市...
IPD流程中PDCP是什么意思   32  
  在研发领域,集成产品开发(IPD)流程已经成为企业提升创新效率和市场竞争力的重要手段。然而,资源分配的不合理往往是制约IPD流程效率的关键因素之一。无论是人力资源、财务资源还是技术资源,如何高效分配直接关系到项目的成功与否。优化资源分配不仅能够缩短产品开发周期,还能降低研发成本,提升产品的市场竞争力。因此,掌握资源分配...
IPD流程中CDCP   34  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用