Uzyskanie klucza o maksymalnej wartości w słowniku?

Mam dictionary: klucze są ciągami znaków, wartości są liczbami całkowitymi.

Przykład:

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

Chciałbym otrzymać 'b' jako odpowiedź, ponieważ jest to klucz o wyższej wartości.

Zrobiłem co następuje, używając listy pośredniej z odwróconymi krotkami o wartości klucza:

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

Czy to lepsze (a nawet bardziej eleganckie) podejście?

Author: Darshana, 2008-11-06

19 answers

Możesz użyć operator.itemgetter do tego:

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

I zamiast budowania nowej listy w pamięci użyj stats.iteritems(). Parametr key do funkcji max() jest funkcją, która oblicza klucz, który jest używany do określania rangi elementów.

Zwróć uwagę, że jeśli masz inną parę klucz-wartość 'd': 3000, ta metoda zwróci tylko jedną z dwóch, nawet jeśli obie mają wartość maksymalną.

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

Jeśli używasz Python3:

>>> max(stats.items(), key=operator.itemgetter(1))[0]
'b'
 418
Author: Priyanka Chaudhary,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-22 17:51:35
max(stats, key=stats.get)
 704
Author: A. Coady,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-11 06:24:30

Przetestowałem wiele wariantów i jest to najszybszy sposób na zwrócenie klucza dict z wartością maksymalną:

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

Aby dać ci pomysł, oto kilka metod kandydowania:

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) 

Słownik testowy:

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}

I wyniki testów w Pythonie 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%     --

I pod Pythonem 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%     -- 

Widać, że f1 jest najszybszy pod Pythonem 3.2 i 2.7 (a dokładniej {[6] } u góry tego posta)

 169
Author: the wolf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-22 00:05:54

Jeśli potrzebujesz znać tylko klucz o maksymalnej wartości, możesz to zrobić bez iterkeys lub iteritems, ponieważ iteracja przez słownik w Pythonie jest iteracją przez jego klucze.

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

EDIT:

z komentarzy, @ user1274878:

Jestem nowy w Pythonie. Czy możesz wyjaśnić swoją odpowiedź krok po kroku?

Tak...

Max

Max (iterable [, key])

Max (arg1, arg2, * args [, klucz])

Return największy element w iterowalnym lub największy z dwóch lub więcej argumentów.

Opcjonalny argument key opisuje jak porównać elementy, aby uzyskać maksimum między nimi:

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

Zwrócone wartości zostaną porównane.

Dict

Python dict jest tabelą hash. Klucz dict to hash obiektu zadeklarowanego jako klucz. Ze względu na wydajność iteracji choć dict zaimplementowane jako iteracji poprzez jego klucze.

Dlatego możemy go użyć do pozbycia się operacji uzyskanie listy kluczy.

Zamknięcie

Funkcja zdefiniowana wewnątrz innej funkcji nazywana jest funkcją zagnieżdżoną. Zagnieżdżone funkcje mogą uzyskać dostęp do zmiennych z zakresu zamykającego.

Zmienna stats dostępna poprzez atrybut __closure__ funkcji lambda jako wskaźnik do wartości zmiennej zdefiniowanej w zakresie nadrzędnym.

 46
Author: I159,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-21 06:12:49

Oto kolejny:

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

Funkcja key po prostu zwraca wartość, która powinna być użyta do rankingu i max() zwraca żądany element od razu.

 35
Author: user994998,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-26 22:09:04
key, value = max(stats.iteritems(), key=lambda x:x[1])

Jeśli nie zależy ci na wartości (byłbym zaskoczony, ale) możesz zrobić:

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

Lubię rozpakowywanie krotki lepiej niż [0] indeks dolny na końcu wyrażenia. Nigdy nie podoba mi się czytelność wyrażeń lambda bardzo, ale znaleźć ten lepszy niż operator.itemgetter(1) IMHO.

 30
Author: Tim Ottinger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-30 18:39:59

Biorąc pod uwagę, że więcej niż jeden wpis mój ma wartość maksymalną. Chciałbym zrobić listę kluczy, które mają wartość maksymalną jako ich wartość.

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

To da Ci 'b' i każdy inny klucz max.

Uwaga: dla Pythona 3 Użyj stats.items() zamiast stats.iteritems()

 18
Author: Climbs_lika_Spyder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-07 18:16:33

Aby uzyskać maksymalny klucz / wartość słownika stats:

stats = {'a':1000, 'b':3000, 'c': 100}
  • na podstawie kluczy

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

  • na podstawie wartości

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

Oczywiście, jeśli chcesz uzyskać tylko klucz lub wartość z wyniku, możesz użyć indeksowania krotki. Na przykład, aby uzyskać klucz odpowiadający maksymalnej wartości:

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

Wyjaśnienie

Metoda słownikowa items() w Pythonie 3 zwraca obiekt widoku słownika. Gdy ten obiekt widoku jest iterowany przez funkcję max, otrzymuje on pozycje słownika jako krotki postaci (key, value).

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

Kiedy używasz lambda wyrażenie lambda x: x[1], w każdej iteracji x jest jedną z tych krotek (key, value). Wybierając odpowiedni indeks, wybierasz, czy chcesz porównać według kluczy, czy według wartości.

Python 2

Dla wersji Python 2.2+ , ten sam kod zadziała. Jednak lepiej jest użyć iteritems() metoda słownikowa zamiast items() dla wydajności.

Uwagi

  • Ta odpowiedź jest oparta na komentarzach do odpowiedzi Climbs_lika_Spyder .

  • Użyty kod został przetestowany na Pythonie 3.5.2 i Pythonie 2.7.10 .

 11
Author: Karim Sonbol,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-17 11:28:09

Na rozwiązania iteracyjne poprzez komentarze w wybranej odpowiedzi...

W Pythonie 3:

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

W Pythonie 2:

max(stats.iterkeys(), key=(lambda k: stats[k]))
 9
Author: watsonic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-05 02:03:11

With collections.Counter you could do

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

Jeśli to właściwe, możesz po prostu zacząć od pustego collections.Counter i dodać do niego

>>> stats = collections.Counter()
>>> stats['a'] += 1
:
etc. 
 6
Author: ukrutt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-23 18:58:38

Dzięki, bardzo eleganckie, nie pamiętam, że max pozwala na parametr "kluczowy".

BTW, aby uzyskać prawidłową odpowiedź ('b') musi być:

import operator
stats = {'a':1000, 'b':3000, 'c': 100}
max(stats.iteritems(), key=operator.itemgetter(1))[0]
 4
Author: ricafeal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-06 11:04:28
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')
 4
Author: priya khokher,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-04 06:50:19

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

 2
Author: Jasha,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-10 05:32:18

+1 do @Aric Coady 's najprostsze rozwiązanie.
A także jeden sposób na losowe wybranie jednego z klawiszy o maksymalnej wartości w słowniku:

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
Author: Woooody Amadeus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-02 08:57:23

Przykład:

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

Jeśli chcesz znaleźć wartość max z jej kluczem, może follwing może być prosty, bez żadnych istotnych funkcji.

max(stats, key=stats.get)

Wyjściem jest klucz, który ma wartość maksymalną.

 1
Author: leo022,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-23 04:08:56

Dotarłem tutaj, szukając jak zwrócić mydict.keys() na podstawie wartości mydict.values(). Zamiast tylko jednego zwracanego klucza, chciałem zwrócić górną x liczbę wartości.

To rozwiązanie jest prostsze niż użycie funkcji max() i można łatwo zmienić ilość zwracanych wartości:

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

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

Jeśli chcesz mieć pojedynczy klucz najwyższej rangi, użyj indeksu:

x[0]
['b']

Jeśli chcesz mieć dwa najwyższe klucze rankingowe, po prostu użyj list slicing:

x[:2]
['b', 'a']
 1
Author: ron g,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-12 09:43:56
Counter = 0
for word in stats.keys():
    if stats[word]> counter:
        Counter = stats [word]
print Counter
 0
Author: Erika Sawajiri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-26 12:31:42

Przetestowałem zaakceptowaną odpowiedź i najszybsze rozwiązanie @thewolf na bardzo podstawowej pętli i pętla była szybsza od obu:

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

Wyniki:

Iterating: 3.8201940059661865
List creating: 6.928712844848633
Accepted answer: 5.464320182800293
 0
Author: citizen2077,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-11 16:26:24

A może:

 max(zip(stats.keys(), stats.values()), key=lambda t : t[1])[0]
 0
Author: user3079275,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-04 20:34:57