1213 votes

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

J'ai un dictionary Les clés sont des chaînes de caractères, les valeurs sont des entiers.

Exemple :

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

J'aimerais avoir 'b' comme réponse, puisque c'est la clé avec une valeur plus élevée.

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

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

Cette dernière est-elle la meilleure (ou même la plus élégante) des approches ?

5 votes

Hum, quel est le problème avec max(stats) ?

55 votes

max(stats) utilisera les étiquettes comme clés (elle retournera 'c' étant donné que c'est l'étiquette maximale), max(stats, key=lambda key: stats[key]) est ce que le PO cherchait (ce qui retournera 'b' , étiquette de la valeur maximale indexée). Est-ce que c'est plus clair ?

1677voto

Coady Points 11374
max(stats, key=stats.get)

22 votes

Si tu voulais vraiment le faire de cette manière, tu pourrais faire stats[max(stats, key=stats.get)]

116 votes

@scottmrogowski, ss. Il fournit la clé avec la valeur maximale, comme demandé. La valeur maximale serait simplement max(stats.values()).

41 votes

Cela devrait être la réponse, car c'est la plus simple et c'est exactement ce que le PO a demandé.

746voto

Vous pouvez utiliser operator.itemgetter pour ça :

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 site key au paramètre max() est une fonction qui calcule une clé qui est utilisée pour déterminer comment classer les éléments.

Veuillez noter que si vous aviez une autre paire clé-valeur 'd' : 3000, cette méthode ne retournera que un de la deux même si elles ont toutes deux la valeur maximale.

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

283 votes

Encore plus propre, je pense= max(stats.iterkeys(), key=(lambda key: stats[key]))

36 votes

Pourquoi ne pas simplement utiliser key=lambda x: x[1] ?

57 votes

Dans python 3 la solution (correctement orthographiée) de @Lucretiel échoue. elle devrait être : max(stats.keys(), key=(lambda k : stats[k])) puisque keys() fait maintenant ce que iterkeys() faisait automatiquement.

245voto

the wolf Points 10164

J'ai testé de NOMBREUSES variantes, et c'est le moyen le plus rapide de retourner la clé du 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 d'essai :

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

14 votes

Ça semble louche. f7 c'est comme f1 Il s'agit simplement de ne pas donner de nom à un objet intermédiaire. f7 devrait être (très légèrement) plus rapide que f1 pas beaucoup plus lent. Et c'est ce que j'obtiens : >>> timeit.timeit("f1()","from __main__ import f1, f7, d1", number=10000) 0.26785888786807277 >>> timeit.timeit("f7()","from __main__ import f1, f7, d1", number=10000) 0.26770628307832567

1 votes

Je suis d'accord que f1 est comme f7. J'ai fait un test avec ipython %timeit et les deux ont donné les mêmes performances sur ma machine avec python 2.7. Test : f1 - 18 µs par boucle Test : f2 - 33.7 µs par boucle Test : f3b - 50 µs par boucle Test : f4b - 30.7 µs par boucle Test : f5 - 28 µs par boucle Test : f6 - 23 µs par boucle Test : f7 - 18 µs par boucle Test : f8 - 43.9 µs par boucle Test : f4 - 2.16 ms par boucle Test : f3 - 2.29 ms par boucle

0 votes

F1 est également applicable lorsque max(d, clé) n'est pas disponible.

50voto

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 qui doit être utilisée pour le classement, et max() renvoie immédiatement l'élément demandé.

10 votes

.iterkeys n'est pas nécessaire dans votre réponse (c'est la valeur par défaut lors de l'itération d'un dict). Cependant, notez que la méthode .iteritems récupère à la fois la clé et la valeur en une seule étape, il n'est donc pas nécessaire d'ajouter un paramètre supplémentaire. getitem par clé selon les besoins avec .iterkeys.

0 votes

Il s'agit d'une excellente réponse, car elle indique très clairement ce qui se passe et peut donc être facilement étendue à d'autres situations.

3 votes

Dans la version python3 : max(stats, key=lambda k: stats[k])

42voto

Tim Ottinger Points 824
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 le faire :

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

J'aime mieux le déballage des tuple que l'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 operator.itemgetter(1) IMHO.

10 votes

_ pourrait être utilisé à la place de ignored .

1 votes

@J.F.Sebastian Je suis d'accord ignored est plutôt laid, mais certaines personnes sont contre l'utilisation de _ pour plusieurs raisons. Je pense que le premier extrait est bon même si on ignore la valeur

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X