web-dev-qa-db-fra.com

Obtenir une clé avec une valeur maximale dans le dictionnaire?

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

Exemple: 

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

J'aimerais obtenir 'b' comme réponse, car c'est la clé avec une valeur 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]

Est-ce une approche meilleure (ou même plus élégante)?

645
ricafeal

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 aviez une autre paire clé-valeur 'd': 3000, cette méthode ne renverra que un des deux même si elles ont toutes les 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'
466
unbeknown
max(stats, key=stats.get)
820
A. Coady

J'ai testé de nombreuses variantes, et c'est le moyen le plus rapide de renvoyer la clé de dict avec la valeur max:

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 constater que f1 est le plus rapide sous Python 3.2 et 2.7 (ou, plus complètement, keywithmaxval en haut de ce post)

180
the wolf

Si vous avez besoin de connaître uniquement une clé avec la valeur max, vous pouvez le faire sans iterkeys ni iteritems 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])

MODIFIER:

D'après les commentaires, @ user1274878:

Je suis nouveau sur Python. Pouvez-vous s'il vous plaît expliquer votre réponse en étapes?

Oui...

max

max (itérable [ clé])

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

Renvoie le plus grand élément dans un itérable ou le plus grand de deux arguments ou plus.

L'argument optionnel key explique comment comparer des éléments pour en obtenir le maximum:

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

Les valeurs renvoyées seront comparées.

Dict

Dict Python est une table de hachage. Une clé de dict est le hachage d'un objet déclaré comme clé. Pour des raisons de performance, itération bien qu'un dict implémenté comme 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 __closure__ de la fonction lambda en tant que pointeur sur la valeur de la variable définie dans la portée parente.

50
I159

En voici un autre:

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

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

36
unbeknown
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écompresser le tuple qu'un indice [0] à la fin de l'expression . Je n'ai jamais beaucoup aimé la lisibilité des expressions lambda, mais je trouve celle-ci meilleure que celle de operator.itemgetter (1).

32
Tim Ottinger

Étant donné que plus d'une entrée, ma valeur max. 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" et toute autre clé max aussi.

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

21

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

stats = {'a':1000, 'b':3000, 'c': 100}
  • Basé sur keys

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

  • Basé sur values ​​

>>> max(stats.items(), key = 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 Tuple. Par exemple, pour obtenir la clé correspondant à la valeur maximale:

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

Explication

La méthode du dictionnaire items() en Python 3 renvoie un objet view du dictionnaire. Lorsque cet objet de vue est itéré par la fonction max, il génère les éléments du dictionnaire sous forme de n-uplets de la forme (key, value).

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

Lorsque vous utilisez lambda expression lambda x: x[1], à chaque itération, x est l'un de ces tuples (key, value). Ainsi, en choisissant le bon index, vous choisissez si vous voulez comparer par clés ou par valeurs.

Python 2

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

Remarques

  • Cette réponse est basée sur les commentaires de Climbs_lika_Spyder's réponse .

  • Le code utilisé a été testé sur Python 3.5.2 et Python 2.7.10. 

15
Karim Sonbol

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.

12
leo022
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')
9
priya khokher

Par 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]))
9
watsonic

Avec collections.Counter vous pourriez 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. 
6
ukrutt

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

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]
4
ricafeal

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 supérieur x .

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']
4
ron g
Counter = 0
for Word in stats.keys():
    if stats[Word]> counter:
        Counter = stats [Word]
print Counter
1
Erika Sawajiri

+1 à @Aric Coady la solution la plus simple. 
Et aussi une façon de sélectionner au hasard une des clés avec une 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])
1
Woooody Amadeus

Je n'étais satisfait d'aucune de ces réponses. max sélectionne toujours la première clé avec la valeur maximale. Le dictionnaire peut avoir plusieurs clés avec cette valeur.

def keys_with_top_values(my_dict):
    return [key  for (key, value) in my_dict.items() if value == max(my_dict.values())]

Afficher cette réponse au cas où cela aiderait quelqu'un. Voir ci-dessous SO post

Quel maximum Python choisit-il en cas d'égalité?

0
kslote1

Que diriez-vous:

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

J'ai testé la réponse acceptée ET @ 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
0
citizen2077

Une file d'attente est une solution généralisée qui permet d'extraire les clés n 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'

Note dict.__getitem__ est la méthode appelée par le sucre syntaxique dict[]. Contrairement à dict.get, il retournera KeyError si une clé est introuvable, ce qui ne peut pas se produire ici.

0
jpp