Question

J'ai un dictionnaire : les clés sont des chaînes, les valeurs sont des entiers.

Exemple:

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

Je voudrais obtenir 'b' comme réponse, car c'est la clé avec la valeur la plus élevée.

J'ai fait ce qui suit en utilisant une liste intermédiaire avec des nuplets clé-valeur inversés:

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

Cette approche est-elle la meilleure (ou même la plus élégante)? ??

Était-ce utile?

La solution

Vous pouvez utiliser operator.itemgetter pour cela:

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

Et au lieu de construire une nouvelle liste en mémoire, utilisez stats.iteritems () . Le paramètre key de la fonction max () est une fonction qui calcule une clé utilisée pour déterminer le classement des éléments.

Veuillez noter que si vous deviez disposer d'une autre paire clé-valeur 'd': 3000, cette méthode ne renverra que un des deux , bien qu'ils aient tous deux la valeur maximale.

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

Si vous utilisez Python3:

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

Autres conseils

max(stats, key=stats.get)

J'ai testé DE NOMBREUSES variantes et c’est le moyen le plus rapide de renvoyer la clé de dict avec la valeur maximale:

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

Pour vous donner une idée, voici quelques méthodes candidates:

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) 

Le dictionnaire de test:

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}

Et les résultats du test sous 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%     --

Et sous 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%     -- 

Vous pouvez voir que f1 est le plus rapide sous Python 3.2 et 2.7 (ou, plus complètement, keywithmaxval en haut de ce billet)

Si vous avez besoin de connaître uniquement une clé avec la valeur maximale, vous pouvez le faire sans iterkeys ou itéritems car l'itération via le dictionnaire en Python est l'itération via ses clés.

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

EDIT:

À partir des commentaires, @ user1274878:

  

Je suis nouveau sur Python. Pouvez-vous expliquer votre réponse en plusieurs étapes?

Oui ...

max

  

max (itérable [, clé])

     

max (arg1, arg2, * args [, clé])

     

Renvoie le plus grand élément d'une variable itérable ou le plus grand de deux arguments ou plus.

L'argument facultatif key décrit comment comparer des éléments pour obtenir le maximum entre eux:

lambda <item>: return <a result of operation with item> 

Les valeurs renvoyées seront comparées.

Dict

Python dict est une table de hachage. Une clé de dict est le hachage d'un objet déclaré comme clé. Pour des raisons de performances, itération même si un dict est mis en oeuvre sous forme d'itération à travers ses clés.

Par conséquent, nous pouvons l’utiliser pour éviter d’obtenir une liste de clés.

Fermeture

  

Une fonction définie dans une autre fonction est appelée une fonction imbriquée. Les fonctions imbriquées peuvent accéder aux variables de la portée englobante.

La variable stats disponible via l'attribut __ fermeture __ de la fonction lambda en tant que pointeur sur la valeur de la variable définie dans la portée parente.

En voici un autre:

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

La fonction touche renvoie simplement la valeur à utiliser pour le classement et max () renvoie immédiatement l'élément demandé.

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

Si vous ne vous souciez pas de la valeur (je serais surpris, mais), vous pouvez faire:

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

J'aime mieux décomposer le tuple qu’un indice [0] à la fin de l’expression. Je n’aime jamais beaucoup la lisibilité des expressions lambda, mais je trouve celle-ci meilleure que celle de operator.itemgetter (1) IMHO.

Exemple:

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

si vous voulez trouver la valeur maximale avec sa clé, suivez peut-être la suite, sans fonctions pertinentes.

max(stats, key=stats.get)

la sortie est la clé qui a la valeur max.

Étant donné que plusieurs entrées peuvent avoir la valeur maximale. Je voudrais faire une liste des clés qui ont la valeur max comme valeur.

>>> 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']

Cela vous donnera "b" ainsi que toute autre clé max.

Remarque: pour Python 3, utilisez stats.items () au lieu de stats.iteritems ()

.

Pour obtenir la clé / valeur maximale du dictionnaire stats :

stats = {'a':1000, 'b':3000, 'c': 100}
  • En fonction des touches

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

  • Basé sur des valeurs

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

Bien sûr, si vous souhaitez obtenir uniquement la clé ou la valeur du résultat, vous pouvez utiliser l’indexation par tuple. Par exemple, pour obtenir la clé correspondant à la valeur maximale:

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

Explication

La méthode du dictionnaire items () dans Python 3 renvoie un objet d'affichage de le dictionnaire. Lorsque cet objet de vue est itéré sur la fonction max , il génère les éléments du dictionnaire sous forme de tuples de la forme (clé, valeur) .

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

Lorsque vous utilisez le lambda expression lambda x: x [1] , à chaque itération, x est l’un de ces uplets (clé, valeur) . Ainsi, en choisissant le bon index, vous choisissez si vous souhaitez comparer les clés ou les valeurs.

Python 2

Pour les versions de Python 2.2+, le même code fonctionnera. Cependant, il est préférable d'utiliser iteritems () méthode de dictionnaire au lieu de items () pour la performance.

Notes

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

Selon les solutions itérées via des commentaires dans la réponse sélectionnée ...

En Python 3:

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

En Python 2:

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

Avec collections.Counter , vous pouvez le faire

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

Le cas échéant, vous pouvez simplement commencer par un collections.Counter vide et y ajouter

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

Je suis arrivé ici pour savoir comment retourner mydict.keys () en fonction de la valeur de mydict.values ??() . Au lieu de la seule clé renvoyée, je cherchais à renvoyer le nombre x supérieur

Cette solution est plus simple que d'utiliser la fonction max () et vous pouvez facilement modifier le nombre de valeurs renvoyées:

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

x = sorted(stats, key=(lambda key:stats[key]), reverse=True)
['b', 'a', 'c']

Si vous voulez la clé la plus haute, utilisez simplement l'index:

x[0]
['b']

Si vous voulez les deux clés les mieux classées, utilisez simplement le découpage en tranches:

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

Merci, très élégant, je ne me souvenais pas que max permettait une "clé". paramètre.

BTW, pour obtenir la bonne réponse ('b'), il doit être:

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

max ((valeur, clé) pour la clé, valeur dans stats.items ()) [1]

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

+1 à @Aric Coady Solution.
Et aussi une façon de sélectionner au hasard une des clés de valeur maximale dans le dictionnaire:

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

Une file d'attente est une solution généralisée qui vous permet d'extraire les n clés supérieures, classées par valeur:

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'

Remarque dict .__ getitem __ est la méthode appelée par le sucre syntaxique dict [] . Contrairement à dict.get , il retournera KeyError si une clé n'est pas trouvée, ce qui ne peut pas se produire ici.

J'ai testé la réponse acceptée AND @ thewolf, la solution la plus rapide, par rapport à une boucle très basique et la boucle était plus rapide que les deux:

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

résultats:

Iterating: 3.8201940059661865
List creating: 6.928712844848633
Accepted answer: 5.464320182800293

Que diriez-vous de:

 max(zip(stats.keys(), stats.values()), key=lambda t : t[1])[0]
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top