Tonino Fernandez
Tonino Fernandez

Reputation: 551

Pythonic way of counting max elements by index in a dictionary with list values

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:


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)

Upvotes: 1

Views: 119

Answers (3)

Jamiu S.
Jamiu S.

Reputation: 5721

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}

Upvotes: -1

Axeltherabbit
Axeltherabbit

Reputation: 737

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

Upvotes: 2

Tomerikoo
Tomerikoo

Reputation: 19414

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 Counters 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.

Upvotes: 1

Related Questions