代码之家  ›  专栏  ›  技术社区  ›  Ack

尝试迭代JSON数据以匹配用户输入

  •  1
  • Ack  · 技术社区  · 2 年前

    我尝试迭代JSON数据,直到键到达“teamName”,值到达用户输入的团队。以下是JSON数据的一小部分,其中包括2个团队:

    {'body': [{'conference': 'American Football Conference',
               'conferenceAbv': 'AFC',
               'currentStreak': {'length': '0', 'result': ''},
               'division': 'East',
               'espnLogo1': 'https://a.espncdn.com/combiner/i?img=/i/teamlogos/nfl/500/buf.png',
               'loss': '0',
               'nflComLogo1': 'https://res.cloudinary.com/nflleague/image/private/f_auto/league/giphcy6ie9mxbnldntsf',
               'pa': '0',
               'pf': '0',
               'teamAbv': 'BUF',
               'teamCity': 'Buffalo',
               'teamID': '4',
               'teamName': 'Bills',
               'teamStats': {'Defense': {'defTD': '3',
                                         'defensiveInterceptions': '18',
                                         'fumbles': '20',
                                         'fumblesLost': '10',
                                         'fumblesRecovered': '19',
                                         'passDeflections': '79',
                                         'passingTDAllowed': '18',
                                         'passingYardsAllowed': '3342',
                                         'qbHits': '117',
                                         'rushingTDAllowed': '14',
                                         'rushingYardsAllowed': '1880',
                                         'sacks': '54',
                                         'soloTackles': '719',
                                         'tfl': '86',
                                         'totalTackles': '1054'},
                             'Kicking': {'fgAttempts': '29',
                                         'fgMade': '24',
                                         'fgYds': '0',
                                         'kickYards': '0',
                                         'xpAttempts': '50',
                                         'xpMade': '49'},
                             'Passing': {'int': '18',
                                         'passAttempts': '579',
                                         'passCompletions': '385',
                                         'passTD': '29',
                                         'passYds': '4306'},
                             'Punting': {'puntTouchBacks': '3',
                                         'puntYds': '2334',
                                         'punts': '51',
                                         'puntsin20': '24'},
                             'Receiving': {'recTD': '29',
                                           'recYds': '4306',
                                           'receptions': '385',
                                           'targets': '545'},
                             'Rushing': {'carries': '512',
                                         'rushTD': '22',
                                         'rushYds': '2212'}},
               'tie': '0',
               'wins': '0'},
              {'conference': 'American Football Conference',
               'conferenceAbv': 'AFC',
               'currentStreak': {'length': '0', 'result': ''},
               'division': 'East',
               'espnLogo1': 'https://a.espncdn.com/combiner/i?img=/i/teamlogos/nfl/500/mia.png',
               'loss': '0',
               'nflComLogo1': 'https://res.cloudinary.com/nflleague/image/private/f_auto/league/lits6p8ycthy9to70bnt',
               'pa': '0',
               'pf': '0',
               'teamAbv': 'MIA',
               'teamCity': 'Miami',
               'teamID': '20',
               'teamName': 'Dolphins',
               'teamStats': {'Defense': {'defTD': '4',
                                         'defensiveInterceptions': '15',
                                         'fumbles': '24',
                                         'fumblesLost': '10',
                                         'fumblesRecovered': '25',
                                         'passDeflections': '81',
                                         'passingTDAllowed': '27',
                                         'passingYardsAllowed': '3761',
                                         'qbHits': '140',
                                         'rushingTDAllowed': '15',
                                         'rushingYardsAllowed': '1650',
                                         'sacks': '56',
                                         'soloTackles': '711',
                                         'tfl': '79',
                                         'totalTackles': '1088'},
                             'Kicking': {'fgAttempts': '28',
                                         'fgMade': '24',
                                         'fgYds': '0',
                                         'kickYards': '0',
                                         'xpAttempts': '59',
                                         'xpMade': '58'},
                             'Passing': {'int': '15',
                                         'passAttempts': '566',
                                         'passCompletions': '393',
                                         'passTD': '30',
                                         'passYds': '4698'},
                             'Punting': {'puntTouchBacks': '3',
                                         'puntYds': '2424',
                                         'punts': '53',
                                         'puntsin20': '20'},
                             'Receiving': {'recTD': '30',
                                           'recYds': '4698',
                                           'receptions': '393',
                                           'targets': '549'},
                             'Rushing': {'carries': '456',
                                         'rushTD': '27',
                                         'rushYds': '2308'}},
               'tie': '0',
               'wins': '0'},
    

    以下是我迄今为止所尝试的:

    data = response.json()
    
    userinput_team = input('Enter the team name')
    userteam = str(userinput_team)
    
    def defense(i):
        for key in data["body"][i]:
            value = data["body"][i][key]
            if key == 'teamName' and value == userteam:
                userdefense = data['body'][i]['teamStats']['Defense']
                print(f"Here are the defensive stats for the {value}:\n{userdefense}")
                return
            else:
                return defense(i+1)
            
            
    defense(0)
    

    如果不使用else语句,如果我为userteam输入Bills,由于I已经为0,代码可以正常工作,输出为:

    Here are the defensive stats for the Bills:
    {'fumblesLost': '10', 'defTD': '3', 'fumbles': '20', 'fumblesRecovered': '19', 'soloTackles': '719', 'qbHits': '117', 'passingTDAllowed': '18', 'passDeflections': '79', 'passingYardsAllowed': '3342', 'totalTackles': '1054', 'defensiveInterceptions': '18', 'tfl': '86', 'rushingYardsAllowed': '1880', 'sacks': '54', 'rushingTDAllowed': '14'}
    

    问题是迭代数据,一旦键到达“teamName”并且值到达用户输入的团队,就会停止。我用else语句计算出,如果在第一个索引0中找不到“teamName”和“userteam”,函数将调用自己,并且只会递增1,直到找到为止,但我得到的只是IndexError:list index超出范围,我不知道该怎么办。

    我知道我可以做这样的事情:

    
    data = response.json()
    
    userinput_team = input('Enter the team name')
    userteam = str(userinput_team)
    
    Bills = 0
    Dolphins = 1
    
    userdefense_Bills = data['body'][Bills]['teamStats']['Defense']
    userdefense_Dolphins = data['body'][Dolphins]['teamStats']['Defense']
    
    if userteam == 'Bills':
        print(userdefense_Bills)
    elif userteam == 'Dolphins':
        print(userdefense_Dolphins)
    else:
        print('Team not found')
    

    但考虑到完整的JSON数据由总共32个团队组成,这似乎有违直觉。我是Python新手,所以我不知道我是否遗漏了一些小细节。我搜索过类似的问题,但它们要么是用不同的语言编写的,要么只是在一个JSON级别上。

    4 回复  |  直到 2 年前
        1
  •  0
  •   Mark    2 年前

    由于你只需要第一个匹配,你可以在一个表达式中使用 next() :

    userinput_team = 'Bills'
    
    team_defense = next(
        (
            item['teamStats']['Defense'] 
            for item in data['body'] 
            if item['teamName'] == userinput_team
        ), 
        None. # <- this can be any default value you want for unknown team
    )
    

    这会给你

    {'defTD': '3',
     'defensiveInterceptions': '18',
     'fumbles': '20',
     'fumblesLost': '10',
     'fumblesRecovered': '19',
     'passDeflections': '79',
     'passingTDAllowed': '18',
     'passingYardsAllowed': '3342',
     'qbHits': '117',
     'rushingTDAllowed': '14',
     'rushingYardsAllowed': '1880',
     'sacks': '54',
     'soloTackles': '719',
     'tfl': '86',
     'totalTackles': '1054'}
    

    如果找到团队,否则 None .

        2
  •  0
  •   Hanstjua    2 年前

    根据您上一个代码片段,您正尝试在给定团队名称的情况下检索“Defense”词典。

    你可以这样做:

    team_name = 'Bills'
    
    defense = None
    for team_info in data['body']:
        if team_info['teamName'] == team_name:
            defense = team_info['teamStats']['Defense']
            break
    
    if defense is not None:
        print(defense)
    else:
        print('Team not found')
    
        3
  •  0
  •   Dhairya Koshti    2 年前

    我相信你正试图通过teamName找到teamStats。 我认为下面这样的方法会奏效

    data = response.json()
    
    userinput_team = input('Enter the team name: \n')
    userteam = str(userinput_team)
    
    def defense():
        realData = data['body']
        for key in realData:
            if key['teamName'] == userteam: 
                userdefense = key['teamStats']['Defense']
                print(f"Here are the defensive stats for the {userteam}:\n{userdefense}")
                return
        print('No Data Found')
        
    defense()
    

    既然你已经在循环了,我认为你不需要在防御函数中使用这个参数。

        4
  •  0
  •   Derek Roberts    2 年前

    我宁愿你用 get python dict中的单词,以避免键错误和 filter 匹配任何匹配的名称

    例如:

    def get_defensive_stats(data, userteam):
        # filter to find the team with the matching name
        teams = list(filter(lambda team: team.get('teamName') == userteam, data.get('body', [])))
        
        #any team was found and return its defensive stats
        if teams:
            return teams[0].get('teamStats', {}).get('Defense', {})
        else:
            return {}