¿Obteniendo llave con valor máximo en diccionario?

Tengo un dictionary : las claves son cadenas, los valores son números enteros.

Ejemplo:

 stats = {'a':1000, 'b':3000, 'c': 100} 

Me gustaría obtener 'b' como respuesta, ya que es la clave con un valor más alto.

Hice lo siguiente, utilizando una lista intermedia con tuplas de valor clave invertidas:

 inverse = [(value, key) for key, value in stats.items()] print max(inverse)[1] 

¿Es ese un enfoque mejor (o incluso más elegante)?

Puedes usar operator.itemgetter para eso:

 import operator stats = {'a':1000, 'b':3000, 'c': 100} max(stats.iteritems(), key=operator.itemgetter(1))[0] 

Y en lugar de crear una nueva lista en la memoria, use stats.iteritems() . El parámetro key para la función max() es una función que calcula una clave que se utiliza para determinar cómo clasificar los elementos.

Tenga en cuenta que si tuviera otro par clave-valor ‘d’: 3000, este método solo devolverá uno de los dos aunque ambos tengan el valor máximo.

 >>> import operator >>> stats = {'a':1000, 'b':3000, 'c': 100, 'd':3000} >>> max(stats.iteritems(), key=operator.itemgetter(1))[0] 'b' 

Si usa Python3:

 >>> max(stats.items(), key=operator.itemgetter(1))[0] 'b' 
 max(stats, key=stats.get) 

He probado MUCHAS variantes, y esta es la forma más rápida de devolver la clave de dict con el valor máximo:

 def keywithmaxval(d): """ a) create a list of the dict's keys and values; b) return the key with the max value""" v=list(d.values()) k=list(d.keys()) return k[v.index(max(v))] 

Para darle una idea, aquí hay algunos métodos candidatos:

 def f1(): v=list(d1.values()) k=list(d1.keys()) return k[v.index(max(v))] def f2(): d3={v:k for k,v in d1.items()} return d3[max(d3)] def f3(): return list(filter(lambda t: t[1]==max(d1.values()), d1.items()))[0][0] def f3b(): # same as f3 but remove the call to max from the lambda m=max(d1.values()) return list(filter(lambda t: t[1]==m, d1.items()))[0][0] def f4(): return [k for k,v in d1.items() if v==max(d1.values())][0] def f4b(): # same as f4 but remove the max from the comprehension m=max(d1.values()) return [k for k,v in d1.items() if v==m][0] def f5(): return max(d1.items(), key=operator.itemgetter(1))[0] def f6(): return max(d1,key=d1.get) def f7(): """ a) create a list of the dict's keys and values; b) return the key with the max value""" v=list(d1.values()) return list(d1.keys())[v.index(max(v))] def f8(): return max(d1, key=lambda k: d1[k]) tl=[f1,f2, f3b, f4b, f5, f6, f7, f8, f4,f3] cmpthese.cmpthese(tl,c=100) 

El diccionario de prueba:

 d1={1: 1, 2: 2, 3: 8, 4: 3, 5: 6, 6: 9, 7: 17, 8: 4, 9: 20, 10: 7, 11: 15, 12: 10, 13: 10, 14: 18, 15: 18, 16: 5, 17: 13, 18: 21, 19: 21, 20: 8, 21: 8, 22: 16, 23: 16, 24: 11, 25: 24, 26: 11, 27: 112, 28: 19, 29: 19, 30: 19, 3077: 36, 32: 6, 33: 27, 34: 14, 35: 14, 36: 22, 4102: 39, 38: 22, 39: 35, 40: 9, 41: 110, 42: 9, 43: 30, 44: 17, 45: 17, 46: 17, 47: 105, 48: 12, 49: 25, 50: 25, 51: 25, 52: 12, 53: 12, 54: 113, 1079: 50, 56: 20, 57: 33, 58: 20, 59: 33, 60: 20, 61: 20, 62: 108, 63: 108, 64: 7, 65: 28, 66: 28, 67: 28, 68: 15, 69: 15, 70: 15, 71: 103, 72: 23, 73: 116, 74: 23, 75: 15, 76: 23, 77: 23, 78: 36, 79: 36, 80: 10, 81: 23, 82: 111, 83: 111, 84: 10, 85: 10, 86: 31, 87: 31, 88: 18, 89: 31, 90: 18, 91: 93, 92: 18, 93: 18, 94: 106, 95: 106, 96: 13, 9232: 35, 98: 26, 99: 26, 100: 26, 101: 26, 103: 88, 104: 13, 106: 13, 107: 101, 1132: 63, 2158: 51, 112: 21, 113: 13, 116: 21, 118: 34, 119: 34, 7288: 45, 121: 96, 122: 21, 124: 109, 125: 109, 128: 8, 1154: 32, 131: 29, 134: 29, 136: 16, 137: 91, 140: 16, 142: 104, 143: 104, 146: 117, 148: 24, 149: 24, 152: 24, 154: 24, 155: 86, 160: 11, 161: 99, 1186: 76, 3238: 49, 167: 68, 170: 11, 172: 32, 175: 81, 178: 32, 179: 32, 182: 94, 184: 19, 31: 107, 188: 107, 190: 107, 196: 27, 197: 27, 202: 27, 206: 89, 208: 14, 214: 102, 215: 102, 220: 115, 37: 22, 224: 22, 226: 14, 232: 22, 233: 84, 238: 35, 242: 97, 244: 22, 250: 110, 251: 66, 1276: 58, 256: 9, 2308: 33, 262: 30, 263: 79, 268: 30, 269: 30, 274: 92, 1300: 27, 280: 17, 283: 61, 286: 105, 292: 118, 296: 25, 298: 25, 304: 25, 310: 87, 1336: 71, 319: 56, 322: 100, 323: 100, 325: 25, 55: 113, 334: 69, 340: 12, 1367: 40, 350: 82, 358: 33, 364: 95, 376: 108, 377: 64, 2429: 46, 394: 28, 395: 77, 404: 28, 412: 90, 1438: 53, 425: 59, 430: 103, 1456: 97, 433: 28, 445: 72, 448: 23, 466: 85, 479: 54, 484: 98, 485: 98, 488: 23, 6154: 37, 502: 67, 4616: 34, 526: 80, 538: 31, 566: 62, 3644: 44, 577: 31, 97: 119, 592: 26, 593: 75, 1619: 48, 638: 57, 646: 101, 650: 26, 110: 114, 668: 70, 2734: 41, 700: 83, 1732: 30, 719: 52, 728: 96, 754: 65, 1780: 74, 4858: 47, 130: 29, 790: 78, 1822: 43, 2051: 38, 808: 29, 850: 60, 866: 29, 890: 73, 911: 42, 958: 55, 970: 99, 976: 24, 166: 112} 

Y los resultados de la prueba bajo Python 3.2:

  rate/sec f4 f3 f3b f8 f5 f2 f4b f6 f7 f1 f4 454 -- -2.5% -96.9% -97.5% -98.6% -98.6% -98.7% -98.7% -98.9% -99.0% f3 466 2.6% -- -96.8% -97.4% -98.6% -98.6% -98.6% -98.7% -98.9% -99.0% f3b 14,715 3138.9% 3057.4% -- -18.6% -55.5% -56.0% -56.4% -58.3% -63.8% -68.4% f8 18,070 3877.3% 3777.3% 22.8% -- -45.4% -45.9% -46.5% -48.8% -55.5% -61.2% f5 33,091 7183.7% 7000.5% 124.9% 83.1% -- -1.0% -2.0% -6.3% -18.6% -29.0% f2 33,423 7256.8% 7071.8% 127.1% 85.0% 1.0% -- -1.0% -5.3% -17.7% -28.3% f4b 33,762 7331.4% 7144.6% 129.4% 86.8% 2.0% 1.0% -- -4.4% -16.9% -27.5% f6 35,300 7669.8% 7474.4% 139.9% 95.4% 6.7% 5.6% 4.6% -- -13.1% -24.2% f7 40,631 8843.2% 8618.3% 176.1% 124.9% 22.8% 21.6% 20.3% 15.1% -- -12.8% f1 46,598 10156.7% 9898.8% 216.7% 157.9% 40.8% 39.4% 38.0% 32.0% 14.7% -- 

Y bajo Python 2.7:

  rate/sec f3 f4 f8 f3b f6 f5 f2 f4b f7 f1 f3 384 -- -2.6% -97.1% -97.2% -97.9% -97.9% -98.0% -98.2% -98.5% -99.2% f4 394 2.6% -- -97.0% -97.2% -97.8% -97.9% -98.0% -98.1% -98.5% -99.1% f8 13,079 3303.3% 3216.1% -- -5.6% -28.6% -29.9% -32.8% -38.3% -49.7% -71.2% f3b 13,852 3504.5% 3412.1% 5.9% -- -24.4% -25.8% -28.9% -34.6% -46.7% -69.5% f6 18,325 4668.4% 4546.2% 40.1% 32.3% -- -1.8% -5.9% -13.5% -29.5% -59.6% f5 18,664 4756.5% 4632.0% 42.7% 34.7% 1.8% -- -4.1% -11.9% -28.2% -58.8% f2 19,470 4966.4% 4836.5% 48.9% 40.6% 6.2% 4.3% -- -8.1% -25.1% -57.1% f4b 21,187 5413.0% 5271.7% 62.0% 52.9% 15.6% 13.5% 8.8% -- -18.5% -53.3% f7 26,002 6665.8% 6492.4% 98.8% 87.7% 41.9% 39.3% 33.5% 22.7% -- -42.7% f1 45,354 11701.5% 11399.0% 246.8% 227.4% 147.5% 143.0% 132.9% 114.1% 74.4% -- 

Puedes ver que f1 es el más rápido en Python 3.2 y 2.7 (o, más completamente, keywithmaxval en la parte superior de esta publicación)

Si necesita conocer solo una clave con el valor máximo, puede hacerlo sin iterkeys o iteritems porque la iteración a través del diccionario en Python es iteración a través de sus claves.

 max_key = max(stats, key=lambda k: stats[k]) 

EDITAR:

De los comentarios, @ user1274878:

Soy nuevo en Python. ¿Puede por favor explicar su respuesta en pasos?

Sí…

max

max (iterable [, tecla])

max (arg1, arg2, * args [, tecla])

Devuelva el elemento más grande en un iterable o el mayor de dos o más argumentos.

El argumento key opcional describe cómo comparar elementos para obtener el máximo entre ellos:

 lambda : return  

Los valores devueltos serán comparados.

Dictado

Python dict es una tabla hash. Una clave de dict es un hash de un objeto declarado como clave. Debido a razones de rendimiento, la iteración se implementó como una iteración a través de sus claves.

Por lo tanto, podemos usarlo para eliminar la operación de obtener una lista de claves.

Cierre

Una función definida dentro de otra función se llama función anidada. Las funciones anidadas pueden acceder a las variables del ámbito adjunto.

La variable de stats disponible a través del atributo __closure__ de la función lambda como un puntero al valor de la variable definida en el ámbito principal.

Aquí hay otro:

 stats = {'a':1000, 'b':3000, 'c': 100} max(stats.iterkeys(), key=lambda k: stats[k]) 

La key función simplemente devuelve el valor que debe usarse para la clasificación y max() devuelve el elemento solicitado de inmediato.

 key, value = max(stats.iteritems(), key=lambda x:x[1]) 

Si no te importa el valor (me sorprendería, pero) puedes hacerlo:

 key, _ = max(stats.iteritems(), key=lambda x:x[1]) 

Me gusta el desempaquetado de la tupla mejor que un subíndice [0] al final de la expresión. Nunca me ha gustado mucho la legibilidad de las expresiones lambda, pero considero que es mejor que operator.itemgetter (1) IMHO.

Dado que más de una entrada mi tiene el valor máximo. Haría una lista de las claves que tienen el valor máximo como su valor.

 >>> stats = {'a':1000, 'b':3000, 'c': 100, 'd':3000} >>> [key for m in [max(stats.values())] for key,val in stats.iteritems() if val == m] ['b', 'd'] 

Esto te dará ‘b’ y cualquier otra tecla máxima también.

Nota: para python 3 use stats.items() lugar de stats.iteritems()

Ejemplo:

 stats = {'a':1000, 'b':3000, 'c': 100} 

Si desea encontrar el valor máximo con su clave, tal vez seguirlo podría ser simple, sin ninguna función relevante.

 max(stats, key=stats.get) 

La salida es la clave que tiene el valor máximo.

Para obtener la clave / valor máximo de las stats diccionario:

 stats = {'a':1000, 'b':3000, 'c': 100} 
  • Basado en llaves

>>> max(stats.items(), key = lambda x: x[0]) ('c', 100)

  • Basado en valores

>>> max(stats.items(), key = lambda x: x[1]) ('b', 3000)

Por supuesto, si desea obtener solo la clave o el valor del resultado, puede utilizar la indexación de tuplas. Por ejemplo, para obtener la clave correspondiente al valor máximo:

>>> max(stats.items(), key = lambda x: x[1])[0] 'b'

Explicación

Los items() método de diccionario items() en Python 3 devuelven un objeto de vista del diccionario. Cuando este objeto de vista se repite en la función max , genera los elementos del diccionario como tuplas del formulario (key, value) .

>>> list(stats.items()) [('c', 100), ('b', 3000), ('a', 1000)]

Cuando usa la expresión lambda x: x[1] , en cada iteración, x es una de estas tuplas (key, value) . Entonces, al elegir el índice correcto, selecciona si deseas comparar por claves o por valores.

Python 2

Para las versiones de Python 2.2+, el mismo código funcionará. Sin embargo, es mejor usar el método del diccionario iteritems() lugar de los items() para el rendimiento.

Notas

  • Esta respuesta se basa en los comentarios de la respuesta de Climbs_lika_Spyder .

  • El código utilizado se probó en Python 3.5.2 y Python 2.7.10.

Por las soluciones iteradas a través de comentarios en la respuesta seleccionada …

En Python 3:

 max(stats.keys(), key=(lambda k: stats[k])) 

En Python 2:

 max(stats.iterkeys(), key=(lambda k: stats[k])) 
 d = {'A': 4,'B':10} min_v = min(zip(d.values(), d.keys())) # min_v is (4,'A') max_v = max(zip(d.values(), d.keys())) # max_v is (10,'B') 

Con collections.Counter . collections.Counter que podrías hacer.

 >>> import collections >>> stats = {'a':1000, 'b':3000, 'c': 100} >>> stats = collections.Counter(stats) >>> stats.most_common(1) [('b', 3000)] 

Si es apropiado, simplemente puede comenzar con una collections.Counter vacía. collections.Counter y agregue

 >>> stats = collections.Counter() >>> stats['a'] += 1 : etc. 

Llegué aquí buscando la forma de devolver mydict.keys() según el valor de mydict.values() . En lugar de solo la tecla devuelta, estaba buscando devolver el número máximo de valores x .

Esta solución es más sencilla que usar la función max() y puede cambiar fácilmente el número de valores devueltos:

 stats = {'a':1000, 'b':3000, 'c': 100} x = sorted(stats, key=(lambda key:stats[key]), reverse=True) ['b', 'a', 'c'] 

Si desea la clave de clasificación más alta, solo use el índice:

 x[0] ['b'] 

Si desea las dos claves principales de mayor rango, solo use el corte de lista:

 x[:2] ['b', 'a'] 

Gracias, muy elegante, no recuerdo que max permite un parámetro “clave”.

Por cierto, para obtener la respuesta correcta (‘b’) tiene que ser:

 import operator stats = {'a':1000, 'b':3000, 'c': 100} max(stats.iteritems(), key=operator.itemgetter(1))[0] 

max((value, key) for key, value in stats.items())[1]

 Counter = 0 for word in stats.keys(): if stats[word]> counter: Counter = stats [word] print Counter 

+1 a la solución más simple de @Aric Coady .
Y también una forma de seleccionar al azar una de las claves con valor máximo en el diccionario:

 stats = {'a':1000, 'b':3000, 'c': 100, 'd':3000} import random maxV = max(stats.values()) # Choice is one of the keys with max value choice = random.choice([key for key, value in stats.items() if value == maxV]) 

Probé la respuesta aceptada Y la solución más rápida de @ thewolf contra un bucle muy básico y el bucle fue más rápido que ambos:

 import time import operator d = {"a"+str(i): i for i in range(1000000)} def t1(dct): mx = float("-inf") key = None for k,v in dct.items(): if v > mx: mx = v key = k return key def t2(dct): v=list(dct.values()) k=list(dct.keys()) return k[v.index(max(v))] def t3(dct): return max(dct.items(),key=operator.itemgetter(1))[0] start = time.time() for i in range(25): m = t1(d) end = time.time() print ("Iterating: "+str(end-start)) start = time.time() for i in range(25): m = t2(d) end = time.time() print ("List creating: "+str(end-start)) start = time.time() for i in range(25): m = t3(d) end = time.time() print ("Accepted answer: "+str(end-start)) 

resultados:

 Iterating: 3.8201940059661865 List creating: 6.928712844848633 Accepted answer: 5.464320182800293 

Qué tal si:

  max(zip(stats.keys(), stats.values()), key=lambda t : t[1])[0] 

Una cola de almacenamiento dynamic es una solución generalizada que le permite extraer las n claves principales ordenadas por valor:

 from heapq import nlargest stats = {'a':1000, 'b':3000, 'c': 100} res1 = nlargest(1, stats, key=stats.__getitem__) # ['b'] res2 = nlargest(2, stats, key=stats.__getitem__) # ['b', 'a'] res1_val = next(iter(res1)) # 'b' 

Tenga en cuenta que dict.__getitem__ es el método llamado por el dict[] sintáctico de azúcar dict[] . A diferencia de dict.get , devolverá KeyError si no se encuentra una clave, que aquí no puede ocurrir.