'Find the sum of values within the values of a nested Dictionary

This is a question based on nested dictionaries.

We are given a nested dictionary wherein in the outer dictionary, the name of the match is mentioned and the value for the matches is another dictionary with it's key and values respectively and the name of the function is orangecap(d) which accepts a dictionary in the below format.

Here's the sample.

d = {'match1':{'player1':57, 'player2':38}, 'match2':{'player3':9, 'player1':42}, 'match3':{'player2':41, 'player4':63, 'player3':91}}

So I would like to search by the player key and calculate the total sum for each player and return the largest sum.

So the output needs to be ('player3', 100)

This is what i have tried so far but to no avail:

def orangecap(d):
  total=0
  for key,value in d.items():
      for value in d.items():
          if d[key] in d.keys():
              total = total+d[value]
          return(d[key],max(total))


Solution 1:[1]

This is a slightly modified answer taken from a previous answer of mine.

def find_totals(d):
    total = {}
    for match, results in d.items():
        for player, score in results.items():
            total[player] = total.get(player, 0) + score
    highest_score = max(total, key=total.get)
    return highest_score, total[highest_score]

Sample output:

>>> d = {'match1':{'player1':57, 'player2':38}, 'match2':{'player3':9, 'player1':42}, 'match3':{'player2':41, 'player4':63, 'player3':91}}
>>> print find_totals(d)
('player3', 100)

So what's going on with your code?, Let's examine the algorithm:

Firstly, you iterate through the items (keys/values) of d. This is fine, as you're trying to traverse a nested dictionary structure. However instead of traversing the inner most structure using the second for loop (iterating over value, instead of d), you instead traverse d again.

value is now simply a tuple of key/value stores in d, rather than the nested dictionary. d[key] is simply the value mapped to the match keys. So how then could a value be in the list of keys -> d.keys() Your if condition never evaluates to true. Despite this, you end up short-circuiting the entire iteration to the return statement after only two iterations. Which neither returns the correct player (d[key] is the nested dictionary), and max takes an iterable argument, not an int.

You should learn more about basic control flow, data structures, and algorithm design. I would suggest Google's excellent python series.

Solution 2:[2]

Something like this should work:

def orangecap(d):
    players = {}
    for match, scores in d.iteritems():
        for player, score in scores.iteritems():
            if player not in players:
                players[player] = score
            else:
                players[player] += score
    return sorted(players.items(), key=lambda x: x[1])[-1]

This creates a dictionary (players) containing the player's total score. Then it sorts the items from the dictionary using the score and returns the highest.

Solution 3:[3]

Because someone had to do it... Here's a one-liner.

EDIT: no longer a one liner because I realised the player was also meant to be returned. So it's now a one-liner in a function.

def total_score(*, match_results: dict, player_name: str):
    return player_name, sum(score for player_scores in match_results.values() 
                                  for player, score in player_scores.items() 
                                  if player == player_name)

Solution 4:[4]

Here's a possible solution:

from collections import defaultdict

data = {
    'match1': {'player1': 57, 'player2': 38},
    'match2': {'player3': 9, 'player1': 42},
    'match3': {'player2': 41, 'player4': 63, 'player3': 91}
}


def orangecap(d):
    result = defaultdict(int)
    for k, v in data.items():
        for k1, v1 in v.items():
            result[k1] += v1

    return sorted(result.items(), key=lambda x: x[1])[-1]

print(orangecap(data))

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Community
Solution 2 FamousJameous
Solution 3
Solution 4