Wells
Wells

Reputation: 10969

How to join two lists of dictionaries in Python?

I have the following simple data structures:

teams = [ { 'league_id': 1, 'name': 'Kings' }, { 'league_id': 1, 'name': 'Sharkls' }, { 'league_id': 2, 'name': 'Reign' }, { 'league_id': 2, 'name': 'Heat' } ]
leagues = [ { 'league_id': 1, 'name': 'League 1' }, { 'league_id': 2, 'name': 'League 2' } ]

And I have the following dict comprehension:

league_teams = { x['league_id']: [ t['name']
    for t in teams if t['league_id'] == x ['league_id'] ]
    for x in leagues }

Which yields:

{1: ['Kings', 'Sharkls'], 2: ['Reign', 'Heat']}

Is there a simpler way using itertools or something to get that dict? This feels a little cumbersome.

Upvotes: 1

Views: 555

Answers (3)

Moinuddin Quadri
Moinuddin Quadri

Reputation: 48090

You do not need itertools here, instead collections.defaultdict is better choice. Complexity of your solution is O(n*m) whereas with defaultdict, it will be O(n+m).

You can achieve what you want like:

from collections import defaultdict

# create set to store `league_id` in `leagues`. Set holds unique
# values and also searching in set is faster than in normal list
leagues_id = set([item['league_id'] for item in leagues])

my_dict = defaultdict(list)

for item in teams:
    if item['league_id'] in leagues_id:
        my_dict[item['league_id']].append(item['name'])

where at the end my_dict will hold the value:

{1: ['Kings', 'Sharkls'], 2: ['Reign', 'Heat']}

Edit: In case you also want entry in my_dict for the league_id present in leagues, but not in teams, you need to explictly make entries like:

for leagues_id in leagues_ids:
     _ = my_dict[leagues_id]   # Will create empty list for such ids

Upvotes: 1

jez
jez

Reputation: 15359

Here's an adaptation of Moinuddin Quadri's O(n+m) solution that catches the "empty league" case, and which incidentally does not require any modules to be imported. The dict output does double-duty as his league_ids set, and since it's pre-initialized, it does not need to be a collections.defaultdict:

output = { league['league_id']:[] for league in leagues }
for team in teams:
    if team['league_id'] in output:
        output[team['league_id']].append(team['name'])
print(output)

The output is:

{1: ['Kings', 'Sharkls'], 2: ['Reign', 'Heat']}

Upvotes: 2

Laurent LAPORTE
Laurent LAPORTE

Reputation: 22992

Checking t['league_id'] == x['league_id'] looks not necessary.

You can simplify with:

import collections

league_teams = collections.defaultdict(list)
for t in teams:
    league_teams[t['league_id']].append(t['name'])

If you really want itertools for that:

import itertools

league_teams = {k: [t['name'] for t in g]
                for k, g in itertools.groupby(teams, key=lambda t: t['league_id'])}

But it will only work if the teams list is sorted.

Upvotes: 0

Related Questions