Как объединить два списка словарей в Python?
У меня есть следующие простые структуры данных:
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' } ]
И у меня есть следующее dict
понимание:
league_teams = { x['league_id']: [ t['name']
for t in teams if t['league_id'] == x ['league_id'] ]
for x in leagues }
Который дает:
{1: ['Kings', 'Sharkls'], 2: ['Reign', 'Heat']}
Есть ли более простой способ использования itertools
или что-то, чтобы получить этот диктат? Это кажется немного громоздким.
3 ответа
Вот адаптация решения O(n+m) от Moinuddin Quadri, которое охватывает случай "пустой лиги" и которое, кстати, не требует импорта каких-либо модулей. Дикт output
выполняет двойную обязанность как его league_ids
установить, и так как он предварительно инициализирован, он не должен быть 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)
Выход:
{1: ['Kings', 'Sharkls'], 2: ['Reign', 'Heat']}
Вы не должны itertools
здесь вместо collections.defaultdict
это лучший выбор. Сложность вашего решения O(n*m), тогда как с defaultdict
, это будет O(n+m).
Вы можете достичь того, что вы хотите, как:
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'])
где в конце my_dict
будет держать значение:
{1: ['Kings', 'Sharkls'], 2: ['Reign', 'Heat']}
Изменить: Если вы также хотите, чтобы запись в my_dict
для league_id
Присутствует в лигах, но не в командах, вам нужно явно делать записи, такие как:
for leagues_id in leagues_ids:
_ = my_dict[leagues_id] # Will create empty list for such ids
Проверка t['league_id'] == x['league_id']
выглядит не обязательно.
Вы можете упростить с:
import collections
league_teams = collections.defaultdict(list)
for t in teams:
league_teams[t['league_id']].append(t['name'])
Если вы действительно хотите itertools
для этого:
import itertools
league_teams = {k: [t['name'] for t in g]
for k, g in itertools.groupby(teams, key=lambda t: t['league_id'])}
Но это будет работать только в том случае, если список команд отсортирован.