Getting key with maximum value in dictionary?

Viewed 1381885

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

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'

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

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.

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.

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.

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

stats could be an empty dictionary, so using only max(stats, key=stats.get) will break in that situation.

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

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

Which maximum does Python pick in the case of a tie?

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

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

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.

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

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.

For scientific python users, here is a simple solution using Pandas:

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

>>> b

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

Try this:

sorted(dict_name, key=dict_name.__getitem__, reverse=True)[0]

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

This simple function will find the max value with key from a dictionary

def find_max(data_dict):

    # let
    max_key = list(data_dict.keys())[0]

    for key in data_dict:
        if data_dict[max_key] < data_dict[key]:
            max_key = key
            
    return max_key, data_dict[max_key]

key, max_value = find_max(my_dictionary)

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