Попытка перебрать данные JSON для соответствия пользовательскому вводу

У меня есть данные JSON, которые я пытаюсь перебирать, пока ключ не достигнет «teamName», а значение не достигнет команды, которую ввел пользователь. Вот небольшой фрагмент данных JSON, включающий две команды:

{'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, если я ввожу Bills для userteam, поскольку я уже равен 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 я понял, что функция будет вызывать сама себя, если «teamName» и userteam не будут найдены в первом индексе 0, и будет просто увеличиваться на 1, пока они не будут найдены, но все, что я получаю, это IndexError: индекс списка вне диапазона и Я не знаю, что делать.

Я знаю, что могу просто сделать что-то вроде:


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.

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
0
52
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Судя по вашему последнему фрагменту кода, вы пытаетесь получить словарь «Защита» по названию команды.

Вы можете сделать что-то вроде этого:

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

Я полагаю, вы пытаетесь найти статистику команды по имени команды. Я думаю, что-то вроде ниже будет работать

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()

Поскольку вы уже выполняете цикл, я не думаю, что вам нужен этот параметр в функции защиты.

Ответ принят как подходящий

Поскольку вам нужно только первое совпадение, вы можете сделать это в одном выражении, используя 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.

Принято, поскольку этот ответ прост, но краток, спасибо!

Ack 17.08.2024 07:31

Я бы предпочел, чтобы вы использовали слово get в словаре Python, чтобы избежать ошибок в ключах и 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 {}

Функция получения слова и фильтра делают код намного чище, спасибо!

Ack 17.08.2024 07:31

Другие вопросы по теме