Obtenir la clé avec la 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 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 de valeurs clés inversées:
inverse = [(value, key) for key, value in stats.items()]
print max(inverse)[1]
est-ce là une approche meilleure (ou encore plus élégante)?
19 réponses
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é qui est utilisée pour déterminer comment classer les éléments.
veuillez noter que si vous deviez avoir une autre paire de clés 'd': 3000, cette méthode ne retournera que un des deux même s'ils ont tous 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'
j'ai testé de nombreuses variantes, et c'est le moyen le plus rapide pour retourner 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 test du dictionnaire:
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 des tests 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 post)
si vous avez besoin de connaître seulement une clé avec la valeur max, vous pouvez le faire sans iterkeys
ou iteritems
parce que l'itération à travers le dictionnaire en Python est l'itération à travers ses clés.
max_key = max(stats, key=lambda k: stats[k])
EDIT:
Dans les commentaires, @user1274878 :
je suis nouveau en python. Pouvez-vous expliquer votre réponse par étapes?
Oui...
max
max(itératif [,])
max (arg1, arg2, * args [, key])
renvoie le plus grand article dans un itérable ou le plus grand de deux arguments ou plus.
l'argument optionnel key
décrit comment comparer des éléments pour obtenir un maximum parmi eux:
lambda <item>: return <a result of operation with item>
les valeurs retournées seront comparer.
Dict
Python dict est une table de hachage. Une clé de dict est un hachage d'un objet déclaré comme une clé. En raison de raisons de performance itération bien qu'un dict mis en œuvre comme itération à travers ses clés.
donc nous pouvons l'utiliser pour supprimer l'opération d'obtention d'une liste de clés.
fermeture
Une fonction définie à l'intérieur d'une autre fonction est appelée une fonction imbriquée. Les fonctions imbriquées peuvent accéder aux variables du champ d'application.
la variable stats
disponible par l'attribut __closure__
de la fonction lambda
comme indicateur de la valeur de la variable définie dans le champ d'application parent.
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é.
key, value = max(stats.iteritems(), key=lambda x:x[1])
Si vous ne se soucient pas de la valeur (je serais surpris, mais) vous pouvez le faire:
key, _ = max(stats.iteritems(), key=lambda x:x[1])
j'aime le tuple déballage de mieux qu'un [0] indice à la fin de l'expression. Je n'aime pas beaucoup la lisibilité des expressions lambda, mais celle-ci est meilleure que l'opérateur.itemgetter (1) IMHO.
étant donné que plus d'une entrée my ont la valeur max. Je ferais une liste des clés qui ont la valeur max comme leur 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 touche max.
Note: pour python 3 utiliser stats.items()
au lieu de stats.iteritems()
pour obtenir la clé/valeur maximale du dictionnaire stats
:
stats = {'a':1000, 'b':3000, 'c': 100}
- Basé sur clés
>>> max(stats.items(), key = lambda x: x[0])
('c', 100)
- basé sur valeurs
>>> 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 un tuple indexer. Par exemple, pour obtenir la clé correspondant à la valeur maximale:
>>> max(stats.items(), key = lambda x: x[1])[0]
'b'
explication
Le dictionnaire de la méthode items()
en Python 3 renvoie un visualiser les objets du dictionnaire. Lorsque cet objet de vue est itéré, par la fonction max
, il donne les éléments du dictionnaire comme tuples de la forme (key, value)
.
>>> list(stats.items())
[('c', 100), ('b', 3000), ('a', 1000)]
lorsque vous utilisez le lambda
expression lambda x: x[1]
, dans chaque itération, x
est l'un de ces tuples (key, value)
. Ainsi, en choisissant le bon indice, à vous de choisir si vous voulez comparer par touches ou par des valeurs.
Python 2
pour les versions Python 2.2+, le même code fonctionnera. Cependant, il est préférable de utilisez iteritems()
méthode du dictionnaire au lieu de items()
pour l'exécution.
Notes
-
cette réponse est basée sur les commentaires sur la réponse de Climps_lika_spyder .
-
le code utilisé a été testé sur Python 3.5.2 et python 2.7.10 .
par les solutions itérées via les 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 pourriez le faire
>>> import collections
>>> stats = {'a':1000, 'b':3000, 'c': 100}
>>> stats = collections.Counter(stats)
>>> stats.most_common(1)
[('b', 3000)]
s'il y a lieu, vous pouvez simplement commencer par un collections.Counter
vide et y ajouter
>>> stats = collections.Counter()
>>> stats['a'] += 1
:
etc.
merci, très élégant, Je ne me souviens pas que max autorise un paramètre "clé".
BTW, pour obtenir la bonne réponse ("b"):
import operator
stats = {'a':1000, 'b':3000, 'c': 100}
max(stats.iteritems(), key=operator.itemgetter(1))[0]
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')
+1 à @Aric Coady est la solution la plus simple.
Et aussi une façon de choisir au hasard une des clés avec la valeur max 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])
exemple:
stats = {'a':1000, 'b':3000, 'c': 100}
si vous voulez trouver la valeur max avec sa clé, peut-être follwing pourrait être simple, sans aucune fonction pertinente.
max(stats, key=stats.get)
la sortie est la clé qui a la valeur max.
je suis arrivé ici pour chercher comment retourner mydict.keys()
basé sur la valeur de mydict.values()
. Au lieu d'une seule clé retournée, je cherchais à retourner le nombre de valeurs x supérieur.
cette solution est plus simple que d'utiliser la fonction max()
et vous pouvez facilement changer le nombre de valeurs retourné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é de classement la plus élevée, il suffit d'utiliser l'indice:
x[0]
['b']
si vous voulez les deux plus hautes touches de classement, il suffit d'utiliser le tranchage de liste:
x[:2]
['b', 'a']
Counter = 0
for word in stats.keys():
if stats[word]> counter:
Counter = stats [word]
print Counter
j'ai testé la réponse acceptée et la solution la plus rapide de @thewolf sur 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]