python - sacar - Obtención del índice del artículo máximo o mínimo devuelto utilizando max()/min() en una lista
sacar elementos de una lista python (20)
Estoy usando las funciones max
y min
Python en las listas para un algoritmo minimax, y necesito el índice del valor devuelto por max()
o min()
. En otras palabras, necesito saber qué movimiento produjo el valor máximo (en el turno del primer jugador) o mínimo (segundo jugador).
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)
Necesito poder devolver el índice real del valor mínimo o máximo, no solo el valor.
¿Por qué molestarse en agregar índices primero y luego revertirlos? La función Enumerate () es solo un caso especial de uso de la función zip (). Vamos a usarlo de manera apropiada:
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)
Creo que la respuesta anterior resuelve tu problema, pero pensé que compartiría un método que te dé el mínimo y todos los índices en los que aparece el mínimo.
minval = min(mylist)
ind = [i for i, v in enumerate(mylist) if v == minval]
Esto pasa la lista dos veces, pero sigue siendo bastante rápido. Sin embargo, es un poco más lento que encontrar el índice del primer encuentro del mínimo. Entonces, si necesita solo uno de los mínimos, use la solución de , si los necesita todos, use esto.
Después de obtener los valores máximos, intente esto:
max_val = max(list)
index_max = list.index(max_val)
Mucho más simple que muchas opciones.
Digamos que tiene una lista de values = [3,6,1,5]
, y necesita el índice del elemento más pequeño, es decir, index_min = 2
en este caso.
Evite la solución con itemgetter()
presentada en las otras respuestas, y use en su lugar
index_min = min(xrange(len(values)), key=values.__getitem__)
porque no requiere import operator
ni utilizar enumerate
, y siempre es más rápido (punto de referencia a continuación) que una solución que usa itemgetter()
.
Si está lidiando con arrays numpy o puede pagar numpy
como una dependencia, considere también usar
import numpy as np
index_min = np.argmin(values)
Esto será más rápido que la primera solución, incluso si lo aplica a una lista de Python pura si:
- es más grande que algunos elementos (aproximadamente 2 ** 4 elementos en mi máquina)
- Puede pagar la copia de memoria de una lista pura a una matriz
numpy
Como señala este punto de referencia:
He ejecutado el benchmark en mi máquina con python 2.7 para las dos soluciones anteriores (azul: python puro, primera solución) (rojo, solución numpy) y para la solución estándar basada en itemgetter()
(negro, solución de referencia). El mismo punto de referencia con Python 3.5 mostró que los métodos comparan exactamente el mismo caso de Python 2.7 presentado anteriormente.
Digamos que tienes una lista como:
a = [9,8,7]
Los dos métodos siguientes son formas bastante compactas de obtener una tupla con el elemento mínimo y su índice. Ambos toman un tiempo similar para procesar. Me gusta más el método zip, pero ese es mi gusto.
método 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)
método de enumeración
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)
Esto es simplemente posible usando las funciones enumerate()
y max()
integradas y el argumento de la key
opcional de la función max()
y una expresión lambda simple:
theList = [1, 5, 10]
maxIndex, maxValue = max(enumerate(theList), key=lambda v: v[1])
# => (2, 10)
En los documentos para max()
dice que el argumento key
espera una función como en la función list.sort()
. También vea el Cómo ordenar .
Funciona igual para min()
. Por cierto, devuelve el primer valor máximo / mínimo.
Mientras sepa cómo usar lambda y el argumento "clave", una solución simple es:
max_index = max( range( len(my_list) ), key = lambda index : my_list[ index ] )
No tengo suficiente reputación para comentar sobre la respuesta existente.
Pero para https://.com/a/11825864/3920439 responda
Esto funciona para los enteros, pero no funciona para la matriz de flotantes (al menos en Python 3.6) TypeError: list indices must be integers or slices, not float
Posiblemente una solución más simple sería convertir la matriz de valores en una matriz de valores, pares de índices, y tomar el máximo / mínimo de eso. Esto daría el índice mayor / menor que tiene el máximo / mínimo (es decir, los pares se comparan primero comparando el primer elemento, y luego comparando el segundo elemento si los primeros son iguales). Tenga en cuenta que no es necesario crear realmente la matriz, ya que los generadores permiten el mínimo / máximo como entrada.
values = [3,4,5]
(m,i) = max((v,i) for i,v in enumerate(values))
print (m,i) #(5, 2)
Puede encontrar el índice y el valor mínimo / máximo al mismo tiempo si enumera los elementos en la lista, pero realiza el mínimo / máximo en los valores originales de la lista. Al igual que:
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 esta manera, la lista solo se recorrerá una vez por mín (o máx).
Si desea encontrar el índice de max dentro de una lista de números (lo que parece ser su caso), le sugiero que use numpy:
import numpy as np
ind = np.argmax(mylist)
Simple como eso :
stuff = [2, 4, 8, 15, 11]
index = stuff.index(max(stuff))
Solo una pequeña adición a lo que ya se ha dicho. values.index(min(values))
parece devolver el índice más pequeño de min. Lo siguiente obtiene el índice más grande:
values.reverse()
(values.index(min(values)) + len(values) - 1) % len(values)
values.reverse()
La última línea se puede omitir si el efecto secundario de revertir en el lugar no importa.
Recorrer todas las ocurrencias.
indices = []
i = -1
for _ in range(values.count(min(values))):
i = values[i + 1:].index(min(values)) + i + 1
indices.append(i)
Por el bien de la brevedad. Probablemente sea una mejor idea almacenar en caché min(values), values.count(min)
fuera del bucle.
También me interesó esto y perfplot algunas de las soluciones sugeridas usando perfplot (un proyecto favorito para mí).
Resulta que el argmin de ese numpy ,
numpy.argmin(x)
es el método más rápido para listas lo suficientemente grandes, incluso con la conversión implícita de la list
entrada a un numpy.array
.
Código para generar la trama:
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,
)
Una forma sencilla de encontrar los índices con un valor mínimo en una lista si no desea importar módulos adicionales:
min_value = min(values)
indexes_with_min_value = [i for i in range(0,len(values)) if values[i] == min_value]
Luego elige por ejemplo el primero:
choosen = indexes_with_min_value[0]
Usar la función numpy del módulo numpy.
import numpy as n
x = n.array((3,3,4,7,4,56,65,1))
Para índice de valor mínimo:
idx = n.where(x==x.min())[0]
Para índice de máximo valor:
idx = n.where(x==x.max())[0]
De hecho, esta función es mucho más poderosa. Puede plantear todo tipo de operaciones booleanas Para un índice de valor entre 3 y 60:
idx = n.where((x>3)&(x<60))[0]
idx
array([2, 3, 4, 5])
x[idx]
array([ 4, 7, 4, 56])
Use una matriz numpy y la función argmax ()
a=np.array([1,2,3])
b=np.argmax(a)
print(b) #2
Si varios elementos son máximos, la función devuelve el primero encontrado. Esto es consistente con otras herramientas de preservación de la estabilidad de clasificación, tales como sorted(iterable, key=keyfunc, reverse=True)[0]
Para obtener más que solo el primer uso del método de clasificación.
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)]
if isMinLevel: return values.index(min(values)) else: return values.index(max(values))
list=[1.1412, 4.3453, 5.8709, 0.1314]
list.index(min(list))
Te dará el primer índice de mínimo.