Pythonic way of counting max elements by index in a dictionary with list values
Question:
I want to compare the lists inside a dictionary (as values) by each index, and save in another dictionary how many times each "key" had the highest value.
Let’s put an example, I have this dictionary:
my_dict = {'a': [1, 2, 5], 'b': [2, 1, 4], 'c': [1, 0, 3]}
I want to end up with a dictionary like this:
count_dict = {'a': 2, 'b': 1, 'c': 0}
Because:

at index 0 of the lists we have:
1
from ‘a’ ;2
from ‘b’ ; and1
from ‘c’.So ‘b’ has the highest value for this index and adds one to the count.

at index 1 of the lists we have:
2
from ‘a’ ;1
from ‘b’ ; and0
from ‘c’.So ‘a’ has the highest value for this index and adds one to the count.

at index 2 of the lists we have:
5
from ‘a’ ;4
from ‘b’ ; and3
from ‘c’.So ‘a’ has the highest value for this index and adds one to the count.
I’ve tried with Counter
and max(my_dict, key=my_dict.get)
. But what would be the most pythonic way instead of doing this:
for i in range(len(my_dict['a'])):
max_value = max(my_dict[key][i] for key in my_dict)
for key in my_dict:
if my_dict[key][i] == max_value:
max_count[key] += 1
print(max_count)
Answers:
An alternative approach using zip()
together with enumerate and lambda.
dict_result = {key: 0 for key in my_dict}
for idx, values in enumerate(zip(*my_dict.values())):
max_key = max(my_dict, key=lambda k: my_dict[k][idx])
dict_result[max_key] += 1
print(dict_result)
{'a': 2, 'b': 1, 'c': 0}
You can zip them:
res = {k:0 for k in my_dict}
keys = [*my_dict] # note that order in dictionaries is only guaranteed in python 3.7+
for l in zip(*my_dict.values()):
res[keys[l.index(max(l))]] += 1
You can zip
the values
after manipulating them to contain their respective key:
zip(*([(k, v) for v in l] for k, l in my_dict.items()))
# gives: [(('a', 1), ('b', 2), ('c', 1)), (('a', 2), ('b', 1), ('c', 0)), (('a', 5), ('b', 4), ('c', 3))]
and now for each item, find the max
according to the value, and increment the count of the matching key:
from collections import Counter
my_dict = {'a': [1, 2, 5], 'b': [2, 1, 4], 'c': [1, 0, 3]}
c = Counter()
for item in zip(*([(k, v) for v in l] for k, l in my_dict.items())):
c[max(item, key=lambda x: x[1])[0]] += 1
print(c)
Will print {'a': 2, 'b': 1}
since c
was never added. But the beauty with Counter
s is that even if you do c['c']
you will still get 0
.
This doesn’t rely on the keys’ order or index and so will work for any Python version.