Ottenere la chiave con il massimo valore nel dizionario?
-
06-07-2019 - |
Domanda
Ho un dizionario
: le chiavi sono stringhe, i valori sono numeri interi.
Esempio:
stats = {'a':1000, 'b':3000, 'c': 100}
Vorrei ottenere 'b'
come risposta, poiché è la chiave con un valore più elevato.
Ho fatto quanto segue, usando un elenco intermedio con tuple chiave-valore invertite:
inverse = [(value, key) for key, value in stats.items()]
print max(inverse)[1]
È questo l'approccio migliore (o anche più elegante)? ??
Soluzione
Puoi usare operator.itemgetter
per questo:
import operator
stats = {'a':1000, 'b':3000, 'c': 100}
max(stats.iteritems(), key=operator.itemgetter(1))[0]
E invece di creare un nuovo elenco in memoria usa stats.iteritems ()
. Il parametro key
sulla funzione max ()
è una funzione che calcola una chiave utilizzata per determinare come classificare gli oggetti.
Tieni presente che se dovessi avere un'altra coppia chiave-valore 'd': 3000 che questo metodo restituirà solo uno dei due anche se entrambi hanno il valore massimo.
>>> import operator
>>> stats = {'a':1000, 'b':3000, 'c': 100, 'd':3000}
>>> max(stats.iteritems(), key=operator.itemgetter(1))[0]
'b'
Se si utilizza Python3:
>>> max(stats.items(), key=operator.itemgetter(1))[0]
'b'
Altri suggerimenti
max(stats, key=stats.get)
Ho testato MOLTE varianti e questo è il modo più veloce per restituire la chiave di dict con il valore massimo:
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))]
Per darti un'idea, ecco alcuni metodi candidati:
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)
Il dizionario di prova:
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}
E i risultati del test in 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% --
E in 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% --
Puoi vedere che f1
è il più veloce in Python 3.2 e 2.7 (o, più completamente, keywithmaxval
nella parte superiore di questo post)
Se devi conoscere solo una chiave con il valore massimo, puoi farlo senza iterkeys
o iteritems
perché l'iterazione attraverso il dizionario in Python è l'iterazione attraverso le sue chiavi.
/ p>
max_key = max(stats, key=lambda k: stats[k])
Modifica
Dai commenti, @ user1274878:
Sono nuovo di Python. Puoi spiegare la tua risposta per favore nei passaggi?
Sì ...
max
max (iterable [, key])
max (arg1, arg2, * args [, chiave])
Restituisce l'elemento più grande in un iterabile o il più grande di due o più argomenti.
L'argomento facoltativo chiave
descrive come confrontare gli elementi per ottenere il massimo tra loro:
lambda <item>: return <a result of operation with item>
I valori restituiti verranno confrontati.
Dict
Python dict è una tabella hash. Una chiave di comando è un hash di un oggetto dichiarato come chiave. Per motivi di prestazioni, iterazione attraverso un dict implementato come iterazione tramite le sue chiavi.
Quindi possiamo usarlo per eliminare l'operazione di ottenere un elenco di chiavi.
Chiusura
Una funzione definita all'interno di un'altra funzione è chiamata funzione nidificata. Le funzioni nidificate possono accedere alle variabili dell'ambito incluso.
La variabile stats
disponibile tramite l'attributo __closure__
della funzione lambda
come puntatore al valore della variabile definita nell'ambito genitore.
Eccone un altro:
stats = {'a':1000, 'b':3000, 'c': 100}
max(stats.iterkeys(), key=lambda k: stats[k])
La funzione key
restituisce semplicemente il valore che dovrebbe essere usato per il ranking e max ()
restituisce subito l'elemento richiesto.
key, value = max(stats.iteritems(), key=lambda x:x[1])
Se non ti interessa il valore (sarei sorpreso, ma) puoi farlo:
key, _ = max(stats.iteritems(), key=lambda x:x[1])
Mi piace la tupla che disimballa meglio di un [0] indice alla fine dell'espressione. Non mi è mai piaciuta molto la leggibilità delle espressioni lambda, ma trovo questa migliore di operator.itemgetter (1) IMHO.
Esempio:
stats = {'a':1000, 'b':3000, 'c': 100}
se vuoi trovare il valore massimo con la sua chiave, forse seguire potrebbe essere semplice, senza alcuna funzione rilevante.
max(stats, key=stats.get)
l'output è la chiave che ha il valore massimo.
Dato che più di una voce my ha il valore massimo. Vorrei fare un elenco delle chiavi che hanno il valore massimo come loro valore.
>>> 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']
Questo ti darà 'b' e qualsiasi altro tasto max.
Nota: per python 3 usa stats.items ()
invece di stats.iteritems()
Per ottenere la chiave / valore massimo del dizionario stats
:
stats = {'a':1000, 'b':3000, 'c': 100}
- Basato su tasti
> > > max (stats.items (), chiave = lambda x: x [0])
('c', 100)
- Basato su valori
> > > max (stats.items (), chiave = lambda x: x [1])
('b', 3000)
Naturalmente, se si desidera ottenere solo la chiave o il valore dal risultato, è possibile utilizzare l'indicizzazione tupla. Ad esempio, per ottenere la chiave corrispondente al valore massimo:
> > > max (stats.items (), chiave = lambda x: x [1]) [0]
'B'
Spiegazione
Il metodo del dizionario items ()
in Python 3 restituisce un visualizza oggetto di il dizionario. Quando questo oggetto vista viene ripetuto, tramite la funzione max
, restituisce gli elementi del dizionario come tuple del modulo (chiave, valore)
.
> > > Lista (stats.items ())
[('c', 100), ('b', 3000), ('a', 1000)]
Quando si utilizza lambda
espressione lambda x: x [1]
, in ciascuna iterazione, x
è una di queste tuple (chiave, valore)
. Quindi, scegliendo l'indice giusto, si seleziona se si desidera confrontare in base a chiavi o valori.
Python 2
Per le versioni di Python 2.2+, lo stesso codice funzionerà. Tuttavia, è meglio usare iteritems ()
metodo del dizionario anziché items ()
per le prestazioni.
Note
-
Questa risposta si basa sui commenti sulla la risposta di Climbs_lika_Spyder .
-
Il codice utilizzato è stato testato su Python 3.5.2 e Python 2.7.10.
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')
Per le soluzioni ripetute tramite commenti nella risposta selezionata ...
In Python 3:
max(stats.keys(), key=(lambda k: stats[k]))
In Python 2:
max(stats.iterkeys(), key=(lambda k: stats[k]))
Con collections.Counter
puoi farlo
>>> import collections
>>> stats = {'a':1000, 'b':3000, 'c': 100}
>>> stats = collections.Counter(stats)
>>> stats.most_common(1)
[('b', 3000)]
Se appropriato, potresti semplicemente iniziare con un collection vuoto. Contatore
e aggiungerlo
>>> stats = collections.Counter()
>>> stats['a'] += 1
:
etc.
Sono arrivato qui alla ricerca di come restituire mydict.keys ()
in base al valore di mydict.values ??()
. Invece di restituire solo una chiave, stavo cercando di restituire il x numero di valori superiore.
Questa soluzione è più semplice dell'uso della funzione max ()
e puoi facilmente cambiare il numero di valori restituiti:
stats = {'a':1000, 'b':3000, 'c': 100}
x = sorted(stats, key=(lambda key:stats[key]), reverse=True)
['b', 'a', 'c']
Se vuoi la chiave di classifica più alta, usa solo l'indice:
x[0]
['b']
Se vuoi le prime due chiavi con il punteggio più alto, usa solo la suddivisione in elenchi:
x[:2]
['b', 'a']
Grazie, molto elegante, non mi sono ricordato che max consente una "chiave" parametro.
A proposito, per ottenere la risposta giusta ('b') deve essere:
import operator
stats = {'a':1000, 'b':3000, 'c': 100}
max(stats.iteritems(), key=operator.itemgetter(1))[0]
max ((valore, chiave) per chiave, valore in stats.items ()) [1]
Counter = 0
for word in stats.keys():
if stats[word]> counter:
Counter = stats [word]
print Counter
+1 a @Aric Coady è il più semplice soluzione.
E anche un modo per selezionare casualmente una delle chiavi con valore massimo nel dizionario:
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])
Una coda heap è una soluzione generalizzata che ti consente di estrarre le chiavi n principali ordinate per valore:
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'
Nota dict .__ getitem__
è il metodo chiamato dallo zucchero sintattico dict []
. A differenza di dict.get
, restituirà KeyError
se non viene trovata una chiave, che qui non può verificarsi.
Ho testato la risposta accettata E la soluzione più veloce di thewolf contro un loop molto semplice e il loop è stato più veloce di entrambi:
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))
Risultati:
Iterating: 3.8201940059661865
List creating: 6.928712844848633
Accepted answer: 5.464320182800293
Che ne dici di:
max(zip(stats.keys(), stats.values()), key=lambda t : t[1])[0]