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)?
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'
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 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)
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 (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 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.
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.
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é.
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).
É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()
.
Pour obtenir la clé/valeur maximale du dictionnaire stats
:
stats = {'a':1000, 'b':3000, 'c': 100}
>>> max(stats.items(), key = lambda x: x[0])
('c', 100)
>>> 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.
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.
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')
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]))
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.
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]
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']
Counter = 0
for Word in stats.keys():
if stats[Word]> counter:
Counter = stats [Word]
print Counter
+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])
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
Que diriez-vous:
max(Zip(stats.keys(), stats.values()), key=lambda t : t[1])[0]
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
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.