如何遍历嵌套字典(在嵌套列表中)并将值复制到新列表中

时间:2020-06-25 09:08:38

标签: python loops dictionary iteration nested-lists

我正在尝试对一组电子竞技游戏数据进行一些数据分析。数据格式如下(从json转换):

game_data = [{"match_id":1, "players":[{"player_name":"Tom", "won":True},
                                       {"player_name":"Anna", "won":False}]}, 
             {"match_id":2, "players":[{"player_name":"Tom", "won":False},
                                       {"player_name":"Fred", "won":True}]}]

我想为球员“ Tom”列出一个列表,其中包含他的得失。像这样:

tom_won = [True, False]

到目前为止,我已经尝试过(见下文),但是没有用,所以我希望你们中的一个能够向我展示一种更好的方法。

index = 0
tom_won = []

while index < len(game_data)
   for game_data[index]["players"][0]["won"] in data[index]:
      if game_data[index]["players"][0]["player_name"] == "Tom":
         tom_won.append(game_data[index]["players"][0]["won"])

   for game_data[index]["players"][1]["won"] in data[index]:
      if game_data[index]["players"][1]["player_name"] == "Tom":
         tom_won.append(game_data[index]["players"][1]["won"])
   index += 1

5 个答案:

答案 0 :(得分:3)

您需要遵循自己的结构:

  • 遍历外部数组中的match元素
  • 对于每个数组,从键'players'给定的数组中迭代播放器
  • 为每个玩家检查名字,如果您要寻找的玩家是name
def get_won(data, name):
    result = []
    for match in data:
        for player in match['players']:
            if player['player_name'] == name:
                result.append(player['won'])
  return result

print(get_won(game_data, 'Tom'))  # [True, False]
print(get_won(game_data, 'Fred')) # [True]
print(get_won(game_data, 'Anna')) # [False]                                   

List-comprehension版本

def get_won(data, name):
    return [player['won'] for match in data for player in match['players'] 
                                            if player['player_name'] == name]

答案 1 :(得分:3)

这是一种通过列表理解做到这一点的方法:

all_players = [p for m in game_data for p in m['players']]
tom = [m["won"] for m in all_players if m['player_name'] == "Tom"]

结果为[True, False]

答案 2 :(得分:2)

您在这里:

res = []
for game in game_data:
    for player in game['players']:
        if player['player_name'] == 'Tom':
            res.append(player['won'])
print(res)

输出:

[True, False]

答案 3 :(得分:2)

尝试一下:

game_data = [{"match_id":1, "players":[{"player_name":"Tom", "won":True},
                                       {"player_name":"Anna", "won":False}]}, 
             {"match_id":2, "players":[{"player_name":"Tom", "won":False},
                                       {"player_name":"Fred", "won":True}]}]


tom_won = []

for each_match in game_data:
    for each_player in each_match["players"]:
        player_name = each_player["player_name"]
        if player_name == "Tom":
            tom_won.append(each_player["won"])

此外,您可以使用defaultdict获得所有玩家的成绩:

game_data = [{"match_id":1, "players":[{"player_name":"Tom", "won":True},
                                       {"player_name":"Anna", "won":False}]}, 
             {"match_id":2, "players":[{"player_name":"Tom", "won":False},
                                       {"player_name":"Fred", "won":True}]}]


import collections

player_won = collections.defaultdict(list)
for each_match in game_data:
    for each_player in each_match["players"]:
        player_name = each_player["player_name"]
        player_won[player_name].append(each_player["won"])

我使用的是python2.7,但应轻松更改代码以在python3中运行。

答案 4 :(得分:1)

我建议先处理数据结构,例如:

game_data = [
    {"match_id": 1, "results": {"Tom": True, "Anna": False}}, 
    {"match_id": 2, "results": {"Tom": False, "Fred": True}}
]

然后您可以用来为一位玩家生成摘要:

>>> [match['results']['Tom'] for match in game_data]
[True, False]

这是not a really good data structure,但至少使用起来更容易。

有意义的是在won之间添加一些连贯性:

game_data = [
    {"match_id": 1, "winner": 1, "player_names": ["Anna", "Tom"]}, 
    {"match_id": 2, "winner": 0, "player_names": ["Fred", "Tom"]}, 
]

然后:

def results(match, name):
    return match['player_names'][match['winner']] == name

player_results = [results(match, 'Tom') for match in game_data]

为避免名称重复,您可能也可以为玩家使用标识符:

from collections import namedtuple

Game = namedtuple('Game', ['match_id', 'winner', 'players'])

game_data = [
    Game(match_id=1, winner=1, players=[0, 1]),
    Game(match_id=2, winner=2, players=[1, 2]),
]

player_id = {name: i for i, name in enumerate(['Anna', 'Tom', 'Fred'])}


player_results = [game.winner == player_id['Tom'] for game in game_data]

您是唯一可以真正回答“什么是最佳数据结构”问题的人,但是我希望这会有所帮助。

还请注意,您可以简单地过滤结果以仅显示玩家参加的比赛,例如最后一个数据结构:

[game.winner == player_id['Fred'] for game in game_data if player_id['Fred'] in game.players]

这不是最干净的形式,但是您可以使用迭代器来首先获取玩家参与的游戏,然后获取结果:

def player_games(games, name):
    return (game for game in game_data if player_id[name] in game.players)

[game.winner == player_id['Fred'] for game in player_games(game_data, 'Fred')]
相关问题