Krijgen sleutel met maximale waarde in woordenboek?

Ik heb een dictionary: sleutels zijn tekenreeksen, waarden zijn gehele getallen.

Voorbeeld:

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

Ik wil graag 'b' als antwoord krijgen, omdat dit de sleutel is met een hogere waarde.

Ik deed het volgende, gebruikmakend van een tussenliggende lijst met omgekeerde sleutel-waarde-tupels:

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

Is dat de betere (of zelfs elegantere) benadering?


Antwoord 1, autoriteit 100%

Daarvoor kunt u operator.itemgetter gebruiken:

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

En in plaats van een nieuwe lijst in het geheugen op te bouwen, gebruik je stats.iteritems(). De parameter key van de functie max() is een functie die een sleutel berekent die wordt gebruikt om te bepalen hoe items moeten worden gerangschikt.

Houd er rekening mee dat als u een ander sleutel-waardepaar ‘d’: 3000 zou hebben, deze methode slechts één van de twee zal retourneren, ook al hebben ze beide de maximale waarde.

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

Bij gebruik van Python3:

>>> max(stats.items(), key=operator.itemgetter(1))[0]
'b'

Antwoord 2, autoriteit 206%

max(stats, key=stats.get)

Antwoord 3, autoriteit 32%

Ik heb VEEL varianten getest en dit is de snelste manier om de dictaatsleutel met de maximale waarde te retourneren:

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

Om u een idee te geven, hier zijn enkele kandidaat-methoden:

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) 

Het testwoordenboek:

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}

En de testresultaten onder 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%     --

En onder 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%     -- 

Je kunt zien dat f1 de snelste is onder Python 3.2 en 2.7 (of, vollediger, keywithmaxval bovenaan dit bericht)


Antwoord 4, autoriteit 10%

U kunt gebruiken:

max(d, key = d.get) 
# which is equivalent to 
max(d, key = lambda k : d.get(k))

Om de sleutel, waardepaar terug te geven, gebruik:

max(d.items(), key = lambda k : k[1])

Antwoord 5, autoriteit 10%

Als u alleen een sleutel met de maximale waarde wilt weten, kunt u dit doen zonder iterkeys of iteritems omdat iteratie via het woordenboek in Python iteratie is via zijn sleutels.

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

BEWERKEN:

Uit reacties, @user1274878 :

Ik ben nieuw in python. Kunt u uw antwoord in stappen uitleggen?

Ja…

max

max(iterable[ key])

max(arg1, arg2, *args[ sleutel])

Retourneer het grootste item in een iterabele of de grootste van twee of meer argumenten.

Het optionele argument key beschrijft hoe elementen te vergelijken om er het maximale uit te halen:

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

Geretourneerde waarden worden vergeleken.

Dict

Python dict is een hashtabel. Een key of dict is een hash van een object dat als sleutel is gedeclareerd. Vanwege prestatieredenen is iteratie via een dict geïmplementeerd als iteratie door zijn sleutels.

Daarom kunnen we het gebruiken om het verkrijgen van een sleutellijst te ontdoen.

Sluiting

Een functie die binnen een andere functie is gedefinieerd, wordt een geneste functie genoemd. Geneste functies hebben toegang tot variabelen van het omsluitende bereik.

De variabele stats die beschikbaar is via het kenmerk __closure__ van de functie lambda als een verwijzing naar de waarde van de variabele die is gedefinieerd in het bovenliggende bereik.


Antwoord 6, autoriteit 9%

Voorbeeld:

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

Als je de maximale waarde met zijn sleutel wilt vinden, kan het volgende misschien eenvoudig zijn, zonder relevante functies.

max(stats, key=stats.get)

de uitvoer is de sleutel met de maximale waarde.


Antwoord 7, autoriteit 7%

Hier is er nog een:

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

De functie key retourneert eenvoudig de waarde die moet worden gebruikt voor rangschikking en max() retourneert meteen het gevraagde element.


Antwoord 8, autoriteit 6%

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

Als je niet om waarde geeft (het zou me verbazen, maar), dan kun je het volgende doen:

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

Ik vind het uitpakken van de tuple beter dan een [0] subscript aan het einde van de expressie.
Ik hou nooit zo van de leesbaarheid van lambda-expressies, maar vind deze beter dan de operator.itemgetter(1) IMHO.


Antwoord 9, autoriteit 4%

Aangezien meer dan één item de maximale waarde heeft. Ik zou een lijst maken van de sleutels die de maximale waarde als waarde hebben.

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

Hiermee krijg je ‘b’ en elke andere max-toets.

Opmerking: gebruik voor python 3 stats.items() in plaats van stats.iteritems()


Antwoord 10, autoriteit 3%

Om de maximale sleutel/waarde van het woordenboek stats te verkrijgen:

stats = {'a':1000, 'b':3000, 'c': 100}
  • Gebaseerd op toetsen

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

  • Gebaseerd op waarden

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

Als u alleen de sleutel of waarde uit het resultaat wilt halen, kunt u natuurlijk tuple-indexering gebruiken. Om bijvoorbeeld de sleutel te krijgen die overeenkomt met de maximale waarde:

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

Uitleg

De woordenboekmethode items() in Python 3 retourneert een view object van het woordenboek. Wanneer dit view-object wordt herhaald, door de functie max, levert het de woordenboekitems op als tupels van de vorm (key, value).

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

Als je de lambda gebruikt uitdrukking lambda x: x[1], in elke iteratie is x een van deze tuples (key, value). Dus door de juiste index te kiezen, selecteert u of u wilt vergelijken op sleutels of op waarden.

Python 2

Voor Python 2.2+ releases werkt dezelfde code. Het is echter beter om iteritems() te gebruiken woordenboekmethode in plaats van items() voor prestaties.

Opmerkingen


Antwoord 11, autoriteit 2%

max(stats, key=stats.get) if stats else None

stats kan een leeg woordenboek zijn, dus het gebruik van alleen max(stats, key=stats.get) zal in die situatie niet werken.


Antwoord 12, autoriteit 2%

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

Antwoord 13, autoriteit 2%

Ik was met geen van deze antwoorden tevreden. max kiest altijd de eerste sleutel met de maximale waarde. Het woordenboek kan meerdere sleutels met die waarde hebben.

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

Dit antwoord plaatsen voor het geval iemand er iets aan heeft.
Zie het onderstaande SO-bericht

Welk maximum kiest Python in de geval van een gelijkspel?


Antwoord 14, autoriteit 2%

Volgens de herhaalde oplossingen via opmerkingen in het geselecteerde antwoord…

In Python 3:

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

In Python 2:

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

Antwoord 15, autoriteit 2%

Ik kwam hier op zoek naar hoe ik mydict.keys() terug kon geven op basis van de waarde van mydict.values(). In plaats van slechts die ene sleutel die werd geretourneerd, wilde ik het hoogste x aantal waarden retourneren.

Deze oplossing is eenvoudiger dan het gebruik van de functie max() en u kunt het aantal geretourneerde waarden eenvoudig wijzigen:

stats = {'a':1000, 'b':3000, 'c': 100}
x = sorted(stats, key=(lambda key:stats[key]), reverse=True)
['b', 'a', 'c']

Als u de enige sleutel met de hoogste rangorde wilt, gebruikt u gewoon de index:

x[0]
['b']

Als je de twee hoogste sleutels wilt, gebruik dan list slicing:

x[:2]
['b', 'a']

Antwoord 16

Met collections.Counter zou je kunnen doen

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

Indien van toepassing kunt u gewoon beginnen met een lege collections.Counter en hieraan toevoegen

>>> stats = collections.Counter()
>>> stats['a'] += 1
:
etc. 

Antwoord 17

Veel eenvoudiger te begrijpen aanpak:

mydict = { 'a':302, 'e':53, 'g':302, 'h':100 }
max_value_keys = [key for key in mydict.keys() if mydict[key] == max(mydict.values())]
print(max_value_keys) # prints a list of keys with max value

Uitvoer: [‘a’, ‘g’]

Je kunt nu maar één sleutel kiezen:

maximum = mydict[max_value_keys[0]]

Antwoord 18

Een heap-wachtrij is een algemene oplossing waarmee u de bovenste n-sleutels kunt extraheren, gesorteerd op waarde:

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'

Opmerking dict.__getitem__ is de methode die wordt aangeroepen door de syntactische suiker dict[]. In tegenstelling tot dict.get, retourneert het KeyError als er geen sleutel wordt gevonden, wat hier niet kan.


Antwoord 19

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


Antwoord 20

+1 voor @Aric Coady‘s eenvoudigste oplossing.
En ook een manier om willekeurig een van de sleutels met maximale waarde in het woordenboek te selecteren:

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

Antwoord 21

Counter = 0
for word in stats.keys():
    if stats[word]> counter:
        Counter = stats [word]
print Counter

Antwoord 22

Wat dacht je van:

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

Antwoord 23

Voor wetenschappelijke python-gebruikers is hier een eenvoudige oplossing met Panda’s:

import pandas as pd
stats = {'a': 1000, 'b': 3000, 'c': 100}
series = pd.Series(stats)
series.idxmax()
>>> b

Antwoord 24

Ik heb het geaccepteerde antwoord EN de snelste oplossing van @thewolf getest tegen een zeer eenvoudige lus en de lus was sneller dan beide:

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

resultaten:

Iterating: 3.8201940059661865
List creating: 6.928712844848633
Accepted answer: 5.464320182800293

Antwoord 25

In het geval dat u meer dan één sleutel met dezelfde waarde heeft, bijvoorbeeld:

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

Je zou als volgt een verzameling kunnen krijgen met alle sleutels met een maximale waarde:

from collections import defaultdict
from collections import OrderedDict
groupedByValue = defaultdict(list)
for key, value in sorted(stats.items()):
    groupedByValue[value].append(key)
# {1000: ['a'], 3000: ['b', 'd', 'e'], 100: ['c']}
groupedByValue[max(groupedByValue)]
# ['b', 'd', 'e']

Antwoord 26

In het geval dat de statistieken leeg zijn, kan men een voorwaarde controleren voordat een waardevolle sleutel wordt gevonden, zoals,

stats = {'a':1000, 'b':3000, 'c': 100}
max_key = None
if bool(stats):
   max_key = max(stats, key=stats.get)
print(max_key)

Dit kan eerst controleren of het woordenboek leeg is of niet, en vervolgens verwerken.

>>> b

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Other episodes