Как перебрать список в словаре, получить значение из ключа и добавить в список? - PullRequest
1 голос
/ 26 апреля 2020

Учитывая список диктов, где у каждого дикта есть ключ со списком диктов, следующим образом:

data = [
    {
        "team": {
            "name": "Arsenal",
            "club": {
                "name": "Arsenal",
                "shortName": "Arsenal",
                "abbr": "ARS",
                "id": 1
            },
            "teamType": "FIRST",
            "shortName": "Arsenal",
            "id": 1
        },

        "players": [
            {
                "id": 4985
            },
            {

                "id": 4474
            }]}]

Я хочу создать новый список диктов, где на выходе будет список диктов для каждого игрока в игроках, но когда я добавляю stats_temp к info_all, значение id одинаково для всех игроков каждой команды. Как мне это решить?

Прямо сейчас я получаю следующий вывод из info_all

 info all = [{'id': 4985,
  'team': 'Arsenal',
  'team_id': 1,
  'team_shortName': 'Arsenal'},
{'id': 4985,
      'team': 'Arsenal',
      'team_id': 1,
      'team_shortName': 'Arsenal'}]

Должно быть:

info all = [{'id': 4985,
      'team': 'Arsenal',
      'team_id': 1,
      'team_shortName': 'Arsenal'},
    {'id': 4474,
          'team': 'Arsenal',
          'team_id': 1,
          'team_shortName': 'Arsenal'}]



def deep_get(dictionary, keys, default=None):
    """Get values of nested keys from dict
        Args:
            dictionary(dict): Dict with nested keys
            keys(dict.keys()): "." separated chain of nested keys, ex "info.player.name"
    """
    return reduce(lambda d, key: d.get(key, default) if isinstance(d, dict) else default, keys.split("."), dictionary)


def read_team_squads(data):
    """Read info from ...playerstats.json into flattened
    list of dicts. 
    """
    info_all = []

    for d in data:
        stats_temp = {}
        players = d['players']
        team = d['team']
        stats_temp = \
            {'team' : team['name'],
            'team_id' : deep_get(team, 'club.id'),
            'team_shortName' : deep_get(team, 'club.shortName'),}
        for player in players:
            stats_temp['id'] = player['id']
            info_all.append(stats_temp)
            print(stats_temp)

    print(info_all)
    return info_all

Ответы [ 2 ]

1 голос
/ 26 апреля 2020

Вам нужно переместиться stats_temp в l oop, чтобы избежать проблем со ссылками.

Рассмотрите следующий пример

items = []
for i in range(3):
    tmpd = {'i': i}
    for j in range(3):
        tmpd['j'] = j
        items.append(tmpd)

>>>items
[{'i': 0, 'j': 2},
 {'i': 0, 'j': 2},
 {'i': 0, 'j': 2},
 {'i': 1, 'j': 2},
 {'i': 1, 'j': 2},
 {'i': 1, 'j': 2},
 {'i': 2, 'j': 2},
 {'i': 2, 'j': 2},
 {'i': 2, 'j': 2}]

Сравните это с

items = []
for i in range(3):
    for j in range(3):
        tmpd = {'i': i, 'j': j}
        items.append(tmpd)

>>>items
[{'i': 0, 'j': 0},
 {'i': 0, 'j': 1},
 {'i': 0, 'j': 2},
 {'i': 1, 'j': 0},
 {'i': 1, 'j': 1},
 {'i': 1, 'j': 2},
 {'i': 2, 'j': 0},
 {'i': 2, 'j': 1},
 {'i': 2, 'j': 2}]
0 голосов
/ 26 апреля 2020

Ссылка на диктовку stats_temp является общей для всех игроков. Если вы измените stats_temp['id'] = ... для одного игрока, это изменение будет видно для всех игроков, потому что это один и тот же объект dict.

Чтобы решить его, копируйте dict в каждой итерации l oop:

for player in players:
    stats_temp = dict(stats_temp)   # Insert this line.

Кроме того, вы можете скопировать так:

import copy
...
for player in players:
    stats_temp = copy.deepcopy(stats_temp)

Альтернативно, вы можете создать новый dict в каждой итерации:

for player in players:
    stats_temp = {...}  # Creates a new dict.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...