【问题标题】:How can I iterate through a nested dictionary (withnin a nested list) and copy the values into a new list [closed]如何遍历嵌套字典(在嵌套列表中)并将值复制到新列表中[关闭]
【发布时间】:2020-10-15 16:50:18
【问题描述】:

我正在尝试对一组电子竞技游戏数据进行一些数据分析。数据格式如下(由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_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

【问题讨论】:

  • datadata[index] 一样是什么?
  • 我认为你应该先处理数据结构。这将有助于简化您的代码。
  • while index &lt; len(game_data) 不要在 Python 中这样循环。你几乎总是想要一个 for 循环。
  • 这个任务可以很容易地分成不同的子任务,比如遍历一个列表,访问一个字典的特定字段,以及收集一个列表中的值。之前,他们都在这里被多次询问和回答。我看不出这个带有特定输入数据的问题对未来的任何人有什么用处,我投票结束这个问题,因为需要更多关注

标签: python loops dictionary iteration nested-lists


【解决方案1】:

这是一种使用列表理解的方法:

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】:

    您需要遵循现有的结构:

    • 从外部数组遍历匹配元素
    • 对于每个数组,从键 '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]
    

    【讨论】:

      【解决方案3】:

      给你:

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

      输出:

      [True, False]
      

      【讨论】:

        【解决方案4】:

        试试这个:

        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中运行。

        【讨论】:

          【解决方案5】:

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

          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')]
          

          【讨论】:

            猜你喜欢
            • 2015-12-06
            • 2012-07-09
            • 1970-01-01
            • 2020-11-13
            • 2021-03-19
            • 2021-08-04
            • 2021-11-16
            • 2017-06-17
            • 1970-01-01
            相关资源
            最近更新 更多