I have a dictionary where keys are strings, and values are integers.
stats = {'a': 1, 'b': 3000, 'c': 0}
How do I get the key with the maximum value? In this case, it is 'b'.
Is there a nicer approach than using an intermediate list with reversed key-value tuples?
inverse = [(value, key) for key, value in stats.items()]
print(max(inverse)[1])
29 Answers 29
max(stats, key=stats.get)
15 Comments
stats[max(stats, key=stats.get)]max_value = max(stats.values()); {key for key, value in stats.items() if value == max_value}You can use operator.itemgetter for that:
import operator
stats = {'a': 1000, 'b': 3000, 'c': 100}
max(stats.iteritems(), key=operator.itemgetter(1))[0]
And instead of building a new list in memory use stats.iteritems(). The key parameter to the max() function is a function that computes a key that is used to determine how to rank items.
Please note that if you were to have another key-value pair 'd': 3000 that this method will only return one of the two even though they both have the maximum value.
>>> import operator
>>> stats = {'a': 1000, 'b': 3000, 'c': 100, 'd': 3000}
>>> max(stats.iteritems(), key=operator.itemgetter(1))[0]
'b'
If using Python3:
>>> max(stats.items(), key=operator.itemgetter(1))[0]
'b'
11 Comments
max(stats.iterkeys(), key=(lambda key: stats[key]))key=lambda x: x[1]?max(stats, key=lambda key: stats[key])I have tested MANY variants, and this is the fastest way to return the key of dict with the max value:
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))]
To give you an idea, here are some candidate methods:
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)
The test dictionary:
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}
And the test results under 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% --
And under 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% --
You can see that f1 is the fastest under Python 3.2 and 2.7 (or, more completely, keywithmaxval at the top of this post)
10 Comments
f7 is like f1, just not giving a name to an intermediate object. f7 should be (very slightly) faster than f1, not much slower. And that's what I get: >>> timeit.timeit("f1()","from __main__ import f1, f7, d1", number=10000) 0.26785888786807277 >>> timeit.timeit("f7()","from __main__ import f1, f7, d1", number=10000) 0.26770628307832567You can use:
max(d, key=d.get)
# which is equivalent to
max(d, key=lambda k: d.get(k))
To return the key-value pair use:
max(d.items(), key=lambda k: k[1])
5 Comments
d.items() creates a tuple and the lambda function uses a the value of the tuple as the object to evaluate, instead of the key.max() is O(n) and dict lookups are O(1) on average, so O(n).__getitem__ instead of get to calm the type-checking lintersIf you need to know only a key with the max value you can do it without iterkeys or iteritems because iteration through dictionary in Python is iteration through it's keys.
max_key = max(stats, key=lambda k: stats[k])
EDIT:
From comments, @user1274878 :
I am new to python. Can you please explain your answer in steps?
Yep...
max
max(iterable[, key])
max(arg1, arg2, *args[, key])
Return the largest item in an iterable or the largest of two or more arguments.
The optional key argument describes how to compare elements to get maximum among them:
lambda <item>: return <a result of operation with item>
Returned values will be compared.
Dict
Python dict is a hash table. A key of dict is a hash of an object declared as a key. Due to performance reasons iteration though a dict implemented as iteration through it's keys.
Therefore we can use it to rid operation of obtaining a keys list.
Closure
A function defined inside another function is called a nested function. Nested functions can access variables of the enclosing scope.
The stats variable available through __closure__ attribute of the lambda function as a pointer to the value of the variable defined in the parent scope.
1 Comment
Example:
stats = {'a':1000, 'b':3000, 'c': 100}
if you wanna find the max value with its key, maybe follwing could be simple, without any relevant functions.
max(stats, key=stats.get)
the output is the key which has the max value.
1 Comment
Here is another one:
stats = {'a':1000, 'b':3000, 'c': 100}
max(stats.iterkeys(), key=lambda k: stats[k])
The function key simply returns the value that should be used for ranking and max() returns the demanded element right away.
3 Comments
max(stats, key=lambda k: stats[k])key, value = max(stats.iteritems(), key=lambda x:x[1])
If you don't care about value (I'd be surprised, but) you can do:
key, _ = max(stats.iteritems(), key=lambda x:x[1])
I like the tuple unpacking better than a [0] subscript at the end of the expression. I never like the readability of lambda expressions very much, but find this one better than the operator.itemgetter(1) IMHO.
Comments
max(stats, key=stats.get, default=None)
If stats could be an empty dictionary, using only max(stats, key=stats.get) will otherwise raise ValueError.
This answer is safe to use so long as None is not a possible key in the dictionary.
8 Comments
max(stats, key=stats.get, default=None) instead.Given that more than one entry my have the max value. I would make a list of the keys that have the max value as their value.
>>> 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']
This will give you 'b' and any other max key as well.
Note: For python 3 use stats.items() instead of stats.iteritems()
2 Comments
max were expensive (e.g., a LONG dictionary) I'd recommend [key for m in [max(stats.values())] for key,val in stats.iteritems() if val == m] if you want an one-liner, otherwise compute m = ... beforehand.To get the maximum key/value of the dictionary stats:
stats = {'a':1000, 'b':3000, 'c': 100}
- Based on keys
>>> max(stats.items(), key = lambda x: x[0])
('c', 100)
- Based on values
>>> max(stats.items(), key = lambda x: x[1])
('b', 3000)
Of course, if you want to get only the key or value from the result, you can use tuple indexing. For Example, to get the key corresponding to the maximum value:
>>> max(stats.items(), key = lambda x: x[1])[0]
'b'
Explanation
The dictionary method items() in Python 3 returns a view object of the dictionary. When this view object is iterated over, by the max function, it yields the dictionary items as tuples of the form (key, value).
>>> list(stats.items())
[('c', 100), ('b', 3000), ('a', 1000)]
When you use the lambda expression lambda x: x[1], in each iteration, x is one of these tuples (key, value). So, by choosing the right index, you select whether you want to compare by keys or by values.
Python 2
For Python 2.2+ releases, the same code will work. However, it is better to use iteritems() dictionary method instead of items() for performance.
Notes
This answer is based on the comments on Climbs_lika_Spyder's answer.
The used code was tested on Python 3.5.2 and Python 2.7.10 .
Comments
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')
Comments
I was not satisfied with any of these answers. max always picks the first key with the max value. The dictionary could have multiple keys with that value.
def keys_with_top_values(my_dict):
return [key for (key, value) in my_dict.items() if value == max(my_dict.values())]
Posting this answer in case it helps someone out. See the below SO post
1 Comment
Per the iterated solutions via comments in the selected answer...
In Python 3:
max(stats.keys(), key=(lambda k: stats[k]))
In Python 2:
max(stats.iterkeys(), key=(lambda k: stats[k]))
2 Comments
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)]
If appropriate, you could simply start with an empty collections.Counter and add to it
>>> stats = collections.Counter()
>>> stats['a'] += 1
:
etc.
Comments
I got here looking for how to return mydict.keys() based on the value of mydict.values(). Instead of just the one key returned, I was looking to return the top x number of values.
This solution is simpler than using the max() function and you can easily change the number of values returned:
stats = {'a':1000, 'b':3000, 'c': 100}
x = sorted(stats, key=(lambda key:stats[key]), reverse=True)
['b', 'a', 'c']
If you want the single highest ranking key, just use the index:
x[0]
['b']
If you want the top two highest ranking keys, just use list slicing:
x[:2]
['b', 'a']
2 Comments
max(). It's clear it's the fastest. I thought I'd offer a different solution with the benefit of slicing, which was more useful to me at the timeMuch simpler to understand approach:
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
Output: ['a', 'g']
Now you can choose only one key:
maximum = mydict[max_value_keys[0]]
Comments
A heap queue is a generalised solution which allows you to extract the top n keys ordered by value:
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__ is the method called by the syntactic sugar dict[]. As opposed to dict.get, it will return KeyError if a key is not found, which here cannot occur.
Comments
max((value, key) for key, value in stats.items())[1]
1 Comment
Following are two easy ways to extract key with max value from given dict
import time
stats = {
"a" : 1000,
"b" : 3000,
"c" : 90,
"d" : 74,
"e" : 72,
}
start_time = time.time_ns()
max_key = max(stats, key = stats.get)
print("Max Key [", max_key, "]Time taken (ns)", time.time_ns() - start_time)
start_time = time.time_ns()
max_key = max(stats, key=lambda key: stats[key])
print("Max Key with Lambda[", max_key, "]Time taken (ns)", time.time_ns() - start_time)
Output
Max Key [ b ] Time taken (ns) 3100
Max Key with Lambda [ b ] Time taken (ns) 1782
Solution with Lambda expression seems to be performing better for smaller inputs.
Comments
For scientific python users, here is a simple solution using Pandas:
import pandas as pd
pd.Series({'a': 1000, 'b': 3000, 'c': 100}).idxmax()
>>> b
Comments
Counter = 0
for word in stats.keys():
if stats[word]> counter:
Counter = stats [word]
print Counter
Comments
I tested the accepted answer AND @thewolf's fastest solution against a very basic loop and the loop was faster than both:
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))
results:
Iterating: 3.8201940059661865
List creating: 6.928712844848633
Accepted answer: 5.464320182800293
Comments
+1 to @Aric Coady's simplest solution.
And also one way to random select one of keys with max value in the dictionary:
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])
Comments
In case of stats is empty, one can check a condition before finding valued key like,
stats = {'a':1000, 'b':3000, 'c': 100}
max_key = None
if bool(stats):
max_key = max(stats, key=stats.get)
print(max_key)
This can first check if the dictionary is empty or not, then process.
>>> b
Comments
Just to add a situation where you want to select certain keys instead of all of them:
stats = {'a':1000, 'b':3000, 'c': 100, 'd':3000, 'e':3000}
keys_to_search = ["a", "b", "c"]
max([k for k in keys_to_search], key=lambda x: stats[x])```
Comments
How about:
max(zip(stats.keys(), stats.values()), key=lambda t : t[1])[0]
3 Comments
zip(stats.keys(), stats.values()) is just a longer way to write stats.items(). Once you make that change, your answer will be almost identical to several older answers.items isn't the same as zip. It just produces the same result.In the case you have more than one key with the same value, for example:
stats = {'a':1000, 'b':3000, 'c': 100, 'd':3000, 'e':3000}
You could get a collection with all the keys with max value as follow:
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']
1 Comment
Try this:
sorted(dict_name, key=dict_name.__getitem__, reverse=True)[0]
max(stats)?max(stats)will use the labels as keys (it will return'c', given that's the maximum label),max(stats, key=lambda key: stats[key])is what OP was after (which will return'b', label of maximal indexed value). Is it any clearer?