Extracting values from common keys in multiple dictionaries

Question:

So I am currently working on a coding lab where my goal is to try to combine multiple mapping into a single mapping

Eng_Team = [
    {'player': 'Harry Kane', 'rating': '90'},
    {'player': 'Harry Mcguire', 'rating': '81'},
    {'player': 'Phil Foden', 'rating': '84'},
    {'player': 'Jack Grealish', 'rating': '85'},
    {'player': 'Eric Dier', 'rating': '79'}
]

USA_Team = [
    {'player': 'Christian Pulisic', 'rating': '82'},
    {'player': 'Gio Reyna', 'rating': '79'},
    {'player': 'Weston Mckinnie', 'rating': '78'},
    {'player': 'Sergino Dest', 'rating': '79'},
    {'player': 'Tyler Adams', 'rating': '79'}
]

I tried

player_lookup = ChainMap(USA_Team,Eng_Team)

print(player_lookup['player'])

to try to get the names of players from both dictionaries. However I am getting this error:

TypeError                                 Traceback (most recent call last)
Input In [49], in <cell line: 5>()
      1 from collections import ChainMap
      3 player_lookup = ChainMap(USA_Team,Eng_Team)
----> 5 print(player_lookup['player'])

File ~anaconda3libcollections__init__.py:938, in ChainMap.__getitem__(self, key)
    936 for mapping in self.maps:
    937     try:
--> 938         return mapping[key]             # can't use 'key in mapping' with defaultdict
    939     except KeyError:
    940         pass

TypeError: list indices must be integers or slices, not str

It is to my knowledge that I might have to create a loop function. How would I do so?

Asked By: Rudolf

||

Answers:

You probably were after something like this:

from collections import ChainMap

# this is not a dictionary, but a list of dictionaries
# so, eng_team['player'] wouldn't actually work
eng_team = [
    {'player': 'Harry Kane', 'rating': '90'},
    {'player': 'Harry Mcguire', 'rating': '81'},
    {'player': 'Phil Foden', 'rating': '84'},
    {'player': 'Jack Grealish', 'rating': '85'},
    {'player': 'Eric Dier', 'rating': '79'},
    {'player': 'John Doe', 'rating': 0}
]

# this is also a list of dictionaries, not a dictionary
usa_team = [
    {'player': 'Christian Pulisic', 'rating': '82'},
    {'player': 'Gio Reyna', 'rating': '79'},
    {'player': 'Weston Mckinnie', 'rating': '78'},
    {'player': 'Sergino Dest', 'rating': '79'},
    {'player': 'Tyler Adams', 'rating': '79'},
    {'player': 'John Doe', 'rating': 1}
]

# so, you'd want to create appropriate dictionaries from the data
# (unless you can just define them as dictionaries right away)
eng_team_dict = {p['player']: {**p} for p in eng_team}
usa_team_dict = {p['player']: {**p} for p in usa_team}

# the dictionaries can be chain-mapped
all_players = ChainMap(eng_team_dict, usa_team_dict)

# this then works
print(all_players['Harry Kane'], all_players['Sergino Dest'])
print(list(all_players.keys()))

# note that duplicate keys will be taken from the first dict in 
# the arguments to ChainMap, i.e. `eng_team_dict` in this case
print(all_players['John Doe'])

Output:

{'player': 'Harry Kane', 'rating': '90'} {'player': 'Sergino Dest', 'rating': '79'}
['Christian Pulisic', 'Gio Reyna', 'Weston Mckinnie', 'Sergino Dest', 'Tyler Adams', 'John Doe', 'Harry Kane', 'Harry Mcguire', 'Phil Foden', 'Jack Grealish', 'Eric Dier']
{'player': 'John Doe', 'rating': 0}
Answered By: Grismar

I think what you’re getting stuck on is that you have declared two lists of dictionaries: not two dictionaries. I believe that if you want to combine them into one dictionary you could use something like

player_rating_lookup = {}

for player_dictionary in Eng_Team:
    player_rating_lookup[player_dictionary['player']] = player_dictionary['rating']
    # adds to the player_rating_lookup dictionary:
    # the player name string is the key in this new dictionary, and the rating string is the value.

for player_dictionary in USA_Team:
    player_rating_lookup[player_dictionary['player']] = player_dictionary['rating']
    # you can just iterate over the two lists of dictionaries separately.
Answered By: Yoshimi

What you are looking for should really be a dict that maps each player’s name to its rating, in which case you can chain the two lists of dicts, map the dicts to an itemgetter to produce a sequence of tuples of player name and rating, and then construct a new dict with the sequence:

from operator import itemgetter
from itertools import chain

dict(map(itemgetter('player', 'rating'), chain(Eng_Team, USA_Team)))

This returns:

{'Harry Kane': '90', 'Harry Mcguire': '81', 'Phil Foden': '84', 'Jack Grealish': '85', 'Eric Dier': '79', 'Christian Pulisic': '82', 'Gio Reyna': '79', 'Weston Mckinnie': '78', 'Sergino Dest': '79', 'Tyler Adams': '79'}

Demo: https://replit.com/@blhsing/NotableDeepskyblueDrupal

Answered By: blhsing
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.