DNburtonguster
DNburtonguster

Reputation: 367

Sum dictionary items based on rank

I can sum items in a list of dicts per key like so:

import functools
dict(
    functools.reduce(
        lambda x, y:x.update(y) or x,
        dict1,
        collections.Counter())
)

But given that

dict1 = [{'ledecky': 1, 'king': 2, 'vollmer': 3},
         {'ledecky': 1, 'vollmer': 2, 'king': 3},
         {'schmitt': 1, 'ledecky': 2, 'vollmer': 3}]

how could I sum their values according to medal value, given that:

medal_value = {1: 10.0, 2: 5.0, 3: 3.0}

Such that the final dict would yield:

{'ledecky': 25.0, 'king': 8.0, 'vollmer': 11.0, 'schmitt': 10.0}

Upvotes: 2

Views: 78

Answers (2)

chapelo
chapelo

Reputation: 2562

Just define a lookup function to transform the original dict to a medal values dict:

def lookup(d):
    return dict((k, medal_value[v]) for k, v in d.items())

And apply this function to your update part of the expression:

dict(
    functools.reduce(
        lambda x, y: x.update(lookup(y)) or x, 
        dict1,
        collections.Counter())
)

Upvotes: 1

ospahiu
ospahiu

Reputation: 3525

The get() dictionary function works really well in this example, we either give the newly created dictionary a default value of 0 or add it's current value with the weighted value using our value (the value of dict1) as the search key.

def calculate_points(results, medal_value):
    d = {}
    for item in results:
        for key, value in item.iteritems():
            d[key] = d.get(key, 0) + medal_value[value]
    return d

Sample output:

dict1 = [{'ledecky': 1, 'king': 2, 'vollmer': 3},
     {'ledecky': 1, 'vollmer': 2, 'king': 3},
     {'schmitt': 1, 'ledecky': 2, 'vollmer': 3}]

medal_value = {1 : 10.0, 2 : 5.0, 3 : 3.0}

print calculate_points(dict1, medal_value)
>>> {'ledecky': 25.0, 'king': 8.0, 'schmitt': 10.0, 'vollmer': 11.0}

Upvotes: 2

Related Questions