web-dev-qa-db-de.com

Schlüssel mit maximalem Wert im Wörterbuch erhalten?

Ich habe eine dictionary: Schlüssel sind Strings, Werte sind ganze Zahlen.

Beispiel: 

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

Ich möchte 'b' als Antwort erhalten, da dies der Schlüssel mit einem höheren Wert ist.

Ich habe folgende Schritte ausgeführt und eine Zwischenliste mit umgekehrten Schlüsselwerttupeln verwendet:

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

Ist das der bessere (oder noch elegantere) Ansatz?

645
ricafeal

Sie können operator.itemgetter dafür verwenden:

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

Und anstatt eine neue Liste im Speicher zu erstellen, verwenden Sie stats.iteritems(). Der key-Parameter der max()-Funktion ist eine Funktion, die einen Schlüssel berechnet, der zum Bestimmen der Rangfolge von Elementen verwendet wird.

Wenn Sie ein anderes Schlüsselwertpaar 'd': 3000 haben, gibt diese Methode nur eins der zwei zurück, obwohl beide den Maximalwert haben. 

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

Wenn Sie Python3 verwenden:

>>> max(stats.items(), key=operator.itemgetter(1))[0]
'b'
466
unbeknown
max(stats, key=stats.get)
820
A. Coady

Ich habe VIELE Varianten getestet, und dies ist der schnellste Weg, um den Schlüssel von dict mit dem maximalen Wert zurückzugeben:

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

Um Ihnen eine Idee zu geben, hier einige Kandidatenmethoden:

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) 

Das Testwörterbuch:

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}

Und die Testergebnisse unter 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%     --

Und unter 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%     -- 

Sie sehen, dass f1 unter Python 3.2 und 2.7 der schnellste ist (oder keywithmaxval ganz oben in diesem Beitrag).

180
the wolf

Wenn Sie nur einen Schlüssel mit dem maximalen Wert benötigen, können Sie dies ohne iterkeys oder iteritems tun, da die Iteration durch das Wörterbuch in Python die Iteration durch die Schlüssel ist.

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

BEARBEITEN:

Aus den Kommentaren, @ user1274878:

Ich bin neu im Python. Kannst du bitte deine Antwort in Schritten erklären?

Ja...

max

max (iterable [ key])

max (arg1, arg2, * args [ Schlüssel])

Gibt das größte Element in einem iterierbaren oder das größte von zwei oder mehr Argumenten zurück.

Das optionale Argument key beschreibt, wie Elemente miteinander verglichen werden, um ein Maximum zwischen ihnen zu erhalten:

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

Zurückgegebene Werte werden verglichen.

Dikt

Python-Dikt ist eine Hashtabelle. Ein Schlüssel eines Diktiers ist ein Hash eines als Schlüssel deklarierten Objekts. Aus Leistungsgründen wurde die Iteration durch ein Dict durch ihre Schlüssel implementiert.

Daher können wir es verwenden, um die Erstellung einer Schlüsselliste zu beenden.

Schließung

Eine in einer anderen Funktion definierte Funktion wird als verschachtelte Funktion bezeichnet. Verschachtelte Funktionen können auf Variablen des umschließenden Bereichs zugreifen.

Die Variable stats, die über das Attribut __closure__ der Funktion lambda verfügbar ist, als Zeiger auf den Wert der im übergeordneten Bereich definierten Variablen.

50
I159

Hier ist noch einer:

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

Die Funktion key gibt einfach den Wert zurück, der für das Ranking verwendet werden soll, und max() gibt das geforderte Element sofort zurück.

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

Wenn Sie sich nicht für den Wert interessieren (ich wäre überrascht, aber), können Sie Folgendes tun:

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

Ich mag das Tuple-Auspacken besser als ein [0] -Zeichenwert am Ende des Ausdrucks. Ich mag die Lesbarkeit von Lambda-Ausdrücken nie sehr, aber finde diesen besser als den Operator.itemgetter (1) IMHO.

32
Tim Ottinger

Da mehr als ein Eintrag den Maximalwert haben kann. Ich würde eine Liste der Schlüssel erstellen, die den Maximalwert als ihren Wert haben.

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

Dadurch erhalten Sie 'b' und alle anderen max-Tasten.

Hinweis: Für Python 3 verwenden Sie stats.items() anstelle von stats.iteritems().

21

Um den maximalen Schlüssel/Wert des Wörterbuchs zu erhalten, stats:

stats = {'a':1000, 'b':3000, 'c': 100}
  • Basierend auf keys

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

  • Basierend auf Werten

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

Wenn Sie nur den Schlüssel oder Wert aus dem Ergebnis erhalten möchten, können Sie natürlich die Tuple-Indizierung verwenden. Um beispielsweise den Schlüssel zu erhalten, der dem Maximalwert entspricht:

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

Erklärung

Die Wörterbuchmethode items() in Python 3 gibt ein view-Objekt des Wörterbuchs zurück. Wenn dieses Ansichtsobjekt durch die Funktion max durchlaufen wird, werden die Wörterbuchelemente als Tupel der Form (key, value) ausgegeben.

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

Wenn Sie den lambda Ausdruck lambda x: x[1] verwenden, ist x in jeder Iteration einer dieser Tupel (key, value). Wenn Sie also den richtigen Index auswählen, wählen Sie aus, ob Sie nach Schlüsseln oder nach Werten vergleichen möchten.

Python 2

Bei Python 2.2 und höheren Versionen funktioniert derselbe Code. Es ist jedoch besser, die iteritems() dictionary-Methode anstelle von items() für die Leistung zu verwenden.

Anmerkungen

  • Diese Antwort basiert auf den Kommentaren zu Climbs_lika_Spyder's Antwort .

  • Der verwendete Code wurde auf Python 3.5.2 und Python 2.7.10 getestet. 

15
Karim Sonbol

Beispiel:

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

wenn Sie den maximalen Wert mit seiner Taste finden möchten, könnte das Folgen einfach sein, ohne relevante Funktionen.

max(stats, key=stats.get)

die Ausgabe ist der Schlüssel mit dem maximalen Wert.

12
leo022
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')
9
priya khokher

Für die iterierten Lösungen über Kommentare in der ausgewählten Antwort ... 

In Python 3:

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

In Python 2:

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

Mit collections.Counter geht das

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

Gegebenenfalls können Sie einfach mit einem leeren collections.Counter beginnen und diesen hinzufügen

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

Danke, sehr elegant, ich konnte mich nicht erinnern, dass max einen "Schlüssel" -Parameter erlaubt.

BTW, um die richtige Antwort ('b') zu erhalten, muss es sein:

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

Ich habe hier nach dem Rückgabewert von mydict.keys() gesucht, basierend auf dem Wert von mydict.values(). Anstelle nur eines Schlüssels, der zurückgegeben wurde, wollte ich die obersten x - Anzahl von Werten zurückgeben.

Diese Lösung ist einfacher als die Verwendung der Funktion max(). Sie können die Anzahl der zurückgegebenen Werte einfach ändern:

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

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

Wenn Sie den einzigen Schlüssel mit dem höchsten Rang wünschen, verwenden Sie einfach den Index:

x[0]
['b']

Wenn Sie die obersten zwei Schlüssel mit dem höchsten Rang wünschen, verwenden Sie einfach das Listen-Slicing:

x[:2]
['b', 'a']
4
ron g

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

3
Jasha
Counter = 0
for Word in stats.keys():
    if stats[Word]> counter:
        Counter = stats [Word]
print Counter
1
Erika Sawajiri

+1 zu @Aric Coady s einfachste Lösung. 
Und auch eine Möglichkeit, einen der Schlüssel mit maximalem Wert im Wörterbuch zufällig auszuwählen:

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
Woooody Amadeus

Mit keiner dieser Antworten war ich zufrieden. max wählt immer den ersten Schlüssel mit dem Maximalwert. Das Wörterbuch kann mehrere Schlüssel mit diesem Wert enthalten.

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

Posten Sie diese Antwort, falls sie jemandem hilft. Siehe den folgenden SO Beitrag

Welches Maximum wählt Python bei einem Unentschieden?

0
kslote1

Wie wäre es mit:

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

Ich habe die akzeptierte Antwort von AND @ thewolf gegen eine sehr einfache Schleife getestet und die Schleife war schneller als 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))

ergebnisse:

Iterating: 3.8201940059661865
List creating: 6.928712844848633
Accepted answer: 5.464320182800293
0
citizen2077

Eine Heap-Warteschlange ist eine generalized -Lösung, mit der Sie die obersten n -Tasten nach Wert geordnet extrahieren können:

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'

Hinweis dict.__getitem__ ist die Methode, die vom syntaktischen Zucker dict[] aufgerufen wird. Im Gegensatz zu dict.get wird KeyError zurückgegeben, wenn kein Schlüssel gefunden wird, der hier nicht vorkommt.

0
jpp