2010-07-19 21 views
165

Si tengo un diccionario de Python, ¿cómo obtengo la clave de la entrada que contiene el valor mínimo?Obtener la clave correspondiente al valor mínimo dentro de un diccionario

Estaba pensando en algo que ver con la función min() ...

Dada la entrada:

{320:1, 321:0, 322:3} 

Sería volver 321.

+0

Typo en su declaración declarada? De lo contrario, ¿por qué 321? ¿No debería ser 320? – GreenMatt

+2

@myself: Bien, ahora veo, lo que se quiere es la clave de la entrada donde el valor de la entrada es el mínimo. Mejor redacción a la pregunta, por favor, ya que obviamente otros pensaban lo mismo que yo. – GreenMatt

+1

Día de concientización de estructura de datos: si solo consulta (o quita) el elemento mínimo, considere usar una cola de prioridad o un montón. –

Respuesta

332

Mejor: min(d, key=d.get) - no hay razón para interponer una capa de indirección lambda inútil o extraer los elementos o las teclas!

+0

+1: ¡listo! ¡Probablemente más lento que el objeto pero increíblemente elegante! – MikeD

+0

@Mike: ¿cómo usarías 'itemgetter' aquí? Además, creo que es la solución más rápida. – SilentGhost

+3

@ SilentGhost: No lo harías, no estoy seguro de lo que estaba pensando. – MikeD

3

Editar: esta es una respuesta a original de la pregunta del PO sobre la clave mínima, no es la respuesta mínima.


Usted puede obtener las llaves del dict usando la función keys, y tienes razón sobre el uso de min para encontrar el mínimo de esa lista.

+0

Realmente no merece un voto negativo, ya que la pregunta original del cartel no era tan clara como podría haber sido. – GreenMatt

+0

@ Space_C0wb0y: tal vez puede ser tan amable de notar que el OP editó su pregunta para significar algo diferente, después de que contesté –

34

Aquí es una respuesta que en realidad le da la solución del PO pidió:

>>> d = {320:1, 321:0, 322:3} 
>>> d.items() 
[(320, 1), (321, 0), (322, 3)] 
>>> # find the minimum by comparing the second element of each tuple 
>>> min(d.items(), key=lambda x: x[1]) 
(321, 0) 

Usando d.iteritems() será más eficiente de los diccionarios más grandes, sin embargo.

+3

En lugar de la lambda puede usar 'operator.itemgetter (1)'. – Philipp

+1

en su lugar lamda use d.get – Texom512

+0

Esto no devuelve la clave como se le pidió, sino el par (clave, valor). – EOL

-6

¿Esto es lo que estás buscando?

d = dict() 
d[15.0]='fifteen' 
d[14.0]='fourteen' 
d[14.5]='fourteenandhalf' 

print d[min(d.keys())] 

Prints 'catorce'

+8

-1: no lo que hizo la pregunta. Estás devolviendo el valor con la clave mínima, OP quiere la clave con el valor mínimo –

7

min(d.items(), key=lambda x: x[1])[0]

-1
# python 
d={320:1, 321:0, 322:3} 
reduce(lambda x,y: x if d[x]<=d[y] else y, d.iterkeys()) 
    321 
+0

-1 para reducir en python – MikeD

+0

@miked: ¿por qué reducir-odiar? – eruciform

+5

1) Reducir es generalmente más lento que itertools. 2) La mayoría de las implementaciones de reduce se pueden simplificar con cualquiera o todas. 3) Soy una boquilla gigante para GvR. 4) El módulo de operador hace innecesarias las lambdas más simples, y las lambdas complejas deben definirse como funciones reales de todos modos. Quizás estoy asustado de la programación funcional. ;) – MikeD

3
>>> d = {320:1, 321:0, 322:3} 
>>> min(d, key=lambda k: d[k]) 
321 
+2

¿realmente ejecutó esto? – SilentGhost

+0

Funciona, pero da el resultado 321, no (321, 0)? – tjvr

+0

@SilentGhost, @ blob8108: D'oh! Copiar y pegar snafu. Corregido ahora. –

2

Si no está seguro de que usted no tiene múltiples valores mínimos, sugeriría:

d = {320:1, 321:0, 322:3, 323:0} 
print ', '.join(str(key) for min_value in (min(d.values()),) for key in d if d[key]==min_value) 

"""Output: 
321, 323 
""" 
3

Otro enfoque para abordar la cuestión de varias claves con el mismo valor min:

>>> dd = {320:1, 321:0, 322:3, 323:0} 
>>> 
>>> from itertools import groupby 
>>> from operator import itemgetter 
>>> 
>>> print [v for k,v in groupby(sorted((v,k) for k,v in dd.iteritems()), key=itemgetter(0)).next()[1]] 
[321, 323] 
2

Use min con un iterador (para python 3 use items en lugar de iteritems); en lugar de lambda use el operador itemgetter from, que es más rápido que lambda.

from operator import itemgetter 
min_key, _ = min(d.iteritems(), key=itemgetter(1)) 
3

Para el caso de que usted tiene varias claves mínimas y desea que sea sencillo

def minimums(some_dict): 
    positions = [] # output variable 
    min_value = float("inf") 
    for k, v in some_dict.items(): 
     if v == min_value: 
      positions.append(k) 
     if v < min_value: 
      min_value = v 
      positions = [] # output variable 
      positions.append(k) 

    return positions 

minimums({'a':1, 'b':2, 'c':-1, 'd':0, 'e':-1}) 

['e', 'c'] 
1
d={} 
d[320]=1 
d[321]=0 
d[322]=3 
value = min(d.values()) 
for k in d.keys(): 
    if d[k] == value: 
     print k,d[k] 
+0

¿Alguna idea de cómo calcular el valor más pequeño POR ENCIMA de cero? –

0

comparé cómo las siguientes tres opciones realizan: salida

import random, datetime 

myDict = {} 
for i in range(10000000): 
    myDict[ i ] = random.randint(0, 10000000) 



# OPTION 1 

start = datetime.datetime.now() 

sorted = [] 
for i in myDict: 
    sorted.append((i, myDict[ i ])) 
sorted.sort(key = lambda x: x[1]) 
print(sorted[0][0]) 

end = datetime.datetime.now() 
print(end - start) 



# OPTION 2 

start = datetime.datetime.now() 

myDict_values = list(myDict.values()) 
myDict_keys = list(myDict.keys()) 
min_value = min(myDict_values) 
print(myDict_keys[ myDict_values.index(min_value) ]) 

end = datetime.datetime.now() 
print(end - start) 



# OPTION 3 

start = datetime.datetime.now() 

print(min(myDict, key=myDict.get)) 

end = datetime.datetime.now() 
print(end - start) 

Muestra :

#option 1 
236230 
0:00:14.136808 

#option 2 
236230 
0:00:00.458026 

#option 3 
236230 
0:00:00.824048 
Cuestiones relacionadas