Obtenir l'index de l'élément Max ou min renvoyé en utilisant max()/min() sur une liste

J'utilise les fonctions max et min de Python sur les listes pour un algorithme minimax, et j'ai besoin de l'index de la valeur retournée par max() ou min(). En d'autres termes, j'ai besoin de savoir quel mouvement a produit la valeur max (au tour d'un premier joueur) ou min (deuxième joueur).

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)

Je dois pouvoir retourner l'index réel de la valeur min ou max, pas seulement la valeur.

277
demandé sur Ninjakannon 2010-03-19 02:20:35

20 réponses

if isMinLevel:
    return values.index(min(values))
else:
    return values.index(max(values))
223
répondu too much php 2013-10-27 20:10:51

Dites que vous avez une liste values = [3,6,1,5], et avez besoin de l'index du plus petit élément, c'est-à-dire index_min = 2 dans ce cas.

Évitez la solution avec itemgetter() présentée dans les autres réponses, et utilisez à la place

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

Parce qu'il ne nécessite pas de import operator ni d'utiliser enumerate, et il est toujours plus rapide(benchmark ci-dessous) qu'une solution utilisant itemgetter().

Si vous avez affaire à des tableaux numpy ou si vous pouvez vous permettre numpy en tant que dépendance, envisagez également d'utiliser

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

Ce sera plus rapide que la première solution même si vous l'appliquez à une liste Python pure si:

  • , il est plus grand que quelques éléments (environ 2**4 éléments sur ma machine)
  • Vous pouvez vous permettre la copie mémoire d'une liste pure vers un tableau numpy

Comme le souligne ce point de repère: entrez la description de l'image ici

J'ai exécuté le benchmark sur ma machine avec Python 2.7 pour les deux solutions ci-dessus (bleu: Python pur, première solution) (rouge, solution numpy) et pour la solution standard basée sur itemgetter() (noir, solution de référence). Le même benchmark avec Python 3.5 a montré que les méthodes comparent exactement la même chose du cas Python 2.7 présenté ci-dessus

293
répondu gg349 2016-07-28 10:20:03

Vous pouvez trouver l'index et la valeur min/max en même temps si vous énumérez les éléments de la liste, mais effectuez min/max sur les valeurs d'origine de la liste. Comme ça:

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

De cette façon, la liste ne sera parcourue qu'une fois pour min (ou max).

290
répondu Matt Anderson 2012-07-09 00:32:08

Si vous voulez trouver l'index de max dans une liste de nombres (ce qui semble être votre cas), alors je vous suggère d'utiliser numpy:

import numpy as np
ind = np.argmax(mylist)
87
répondu dr.haz 2012-11-23 17:41:42

Peut-être une solution plus simple serait de transformer le tableau de valeurs en un tableau de valeur,de paires d'index, et de prendre le max/min de cela. Cela donnerait l'indice le plus grand/le plus petit qui a le max / min (c'est-à-dire que les paires sont comparées en comparant d'abord le premier élément, puis en comparant le deuxième élément si les premiers sont les mêmes). Notez qu'il n'est pas nécessaire de créer réellement le tableau, car min/max autorise les générateurs en entrée.

values = [3,4,5]
(m,i) = max((v,i) for i,v in enumerate(values))
print (m,i) #(5, 2)
32
répondu Ant6n 2013-10-19 14:08:07
list=[1.1412, 4.3453, 5.8709, 0.1314]
list.index(min(list))

Vous donnera le premier index du minimum.

22
répondu Andy 2013-09-07 21:38:16

J'étais également intéressé par cela et j'ai comparé certaines des solutions suggérées en utilisant perfplot (un de mes projets pet).

S'avère que argmin de numpy ,

numpy.argmin(x)

Est la méthode la plus rapide pour les listes assez grandes, même avec la conversion implicite de l'entrée list à un numpy.array.

entrez la description de l'image ici


Code pour générer le tracé:

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,
    )
9
répondu Nico Schlömer 2017-12-05 16:05:17

Utilisez la fonction numpy du module numpy.où

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

Pour l'indice de valeur minimale:

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

Pour l'indice de valeur maximale:

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

En fait, cette fonction est beaucoup plus puissant. Vous pouvez poser toutes sortes d'opérations booléennes Pour l'indice de valeur entre 3 et 60:

idx = n.where((x>3)&(x<60))[0]
idx
array([2, 3, 4, 5])
x[idx]
array([ 4,  7,  4, 56])
6
répondu Ishan Tomar 2016-08-25 09:28:08

Ceci est simplement possible en utilisant les fonctions enumerate() et max() intégrées et l'argument key facultatif de la fonction max() et une expression lambda simple:

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

Dans les docs pour max() il est dit que la key argument s'attend à une fonction comme dans l'list.sort() fonction. Voir aussi le Tri comment .

Cela fonctionne de la même manière pour min(). Btw il renvoie la première valeur max / min.

4
répondu Simon Hänisch 2016-11-03 09:01:32

Tant que vous savez comment utiliser lambda et l'argument "key", une solution simple est:

max_index = max( range( len(my_list) ), key = lambda index : my_list[ index ] )
4
répondu Veiga 2017-01-24 22:41:57

Utilise un tableau numpy et la fonction argmax ()

 a=np.array([1,2,3])
 b=np.argmax(a)
 print(b) #2
4
répondu John Misquita 2018-01-29 18:07:41

Je pense que la réponse ci-dessus résout votre problème, mais je pensais partager une méthode qui vous donne le minimum et tous les indices dans lesquels le minimum apparaît.

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

Cela passe la liste deux fois mais est encore assez rapide. Il est cependant légèrement plus lent que de trouver l'indice de la première rencontre de la minimale. Donc, si vous avez besoin d'un seul des minima, utilisez la solution de Matt Anderson , Si vous en avez tous besoin, utilisez ceci.

3
répondu Burak Bağdatlı 2017-05-23 12:26:34

Pourquoi prendre la peine d'ajouter d'abord des indices, puis de les Inverser? La fonction Enumerate() est juste un cas particulier d'utilisation de la fonction zip (). Utilisons-le de manière appropriée:

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)
3
répondu sophist 2015-03-17 13:45:16

Dites que vous avez une liste telle que:

a = [9,8,7]

Les deux méthodes suivantes sont des moyens assez compacts pour obtenir un tuple avec l'élément minimum et son index. Les deux prennent un similaire temps à traiter. J'aime mieux la méthode zip, mais c'est mon goût.

Méthode 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)

Énumérer méthode

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)
3
répondu Pablo MPA 2018-05-06 07:35:54

Après avoir obtenu les valeurs maximales, essayez ceci:

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

Beaucoup plus simple que beaucoup d'options.

3
répondu alpha_989 2018-07-14 07:08:51

Juste un ajout mineur à ce qui a déjà été dit. values.index(min(values)) semble renvoyer le plus petit indice de min. Ce qui suit obtient le plus grand index:

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

La dernière ligne peut être laissée de côté si l'effet secondaire de l'inversion en place n'a pas d'importance.

Pour parcourir toutes les occurrences

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

Par souci de brièveté. C'est probablement une meilleure idée de cache min(values), values.count(min) en dehors de la boucle.

2
répondu hyperbolic 2012-04-06 16:09:02

Un moyen simple de trouver les index avec une valeur minimale dans une liste si vous ne voulez pas importer de modules supplémentaires:

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

, Puis choisissez par exemple le premier:

choosen = indexes_with_min_value[0]
2
répondu antoninstuppa 2016-08-09 12:17:54

Aussi Simple que cela:

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

index = stuff.index(max(stuff))
1
répondu dctremblay 2017-03-12 19:51:48

Ne pas avoir un représentant assez élevé pour commenter la réponse existante.

, Mais pour https://stackoverflow.com/a/11825864/3920439 réponse

Cela fonctionne pour les entiers, mais ne fonctionne pas pour le tableau de flotteurs (au moins en Python 3.6) Il va soulever TypeError: list indices must be integers or slices, not float

1
répondu user3920439 2018-02-19 15:41:55

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

Si plusieurs éléments sont maximaux, la fonction renvoie le premier rencontré. Ceci est compatible avec d'autres outils de préservation de la stabilité de tri tels que sorted(iterable, key=keyfunc, reverse=True)[0]

Pour obtenir plus que le premier, utilisez la méthode de tri.

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)]
0
répondu The Demz 2015-09-17 20:56:34