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)? ??

È stato utile?

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

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
Da

+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]
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top