如何在JSON赛事数据中按指定字段分组并计算时间差?
问题分析与解决方案
需求说明
需要处理包含赛事数据的JSON文件,完成以下操作:
- 先按
Day字段分组,再在每个Day组内按Championship字段二次分组 - 计算每个分组内赛事
Times字段的日期时间差(天/小时/分钟单位)
data.json内容:
[ { "Day": "Giornata 29", "Matches": { "Home": "Egnatia", "Away": "Kukesi", "Times": "19.03. 15:00", "Championship": "CALCIO\nALBANIA Super League\n2023/2024" } }, { "Day": "Giornata 29", "Matches": { "Home": "Egnatia", "Away": "Kukesi", "Times": "20.03. 16:09", "Championship": "CALCIO\nALBANIA Super League\n2023/2024" } }, { "Day": "Giornata 41", "Matches": { "Home": "Lincoln", "Away": "Leyton Orient", "Times": "19.03. 16:00", "Championship": "CALCIO\nINGHILTERRA League One\n2023/2024" } }, { "Day": "Giornata 30", "Matches": { "Home": "Napoli", "Away": "Atalanta", "Times": "30.03. 12:30", "Championship": "CALCIO\nITALIA Serie A\n2023/2024" } } ]
现有代码问题分析
你写的代码存在几个关键问题:
- 变量名冲突:
day和time先被赋值为当前时间和导入的模块,随后又被重新赋值为集合,会覆盖原有值导致潜在错误 - 分组逻辑错误:当前的
championshipList和dayList是分别按单一字段分组,没有实现先Day再Championship的嵌套分组 - 缺少时间处理:没有将字符串格式的
Times转换为可计算的datetime对象,也没有实现时间差的计算逻辑
关键概念讲解
1. 时间字符串转datetime对象
要计算时间差,必须先把Times字段的字符串(比如"19.03. 15:00")转换成datetime对象。用datetime.strptime()方法,指定匹配的格式字符串:
# 格式说明:%d=日,%m=月,%H=24小时制时,%M=分 time_str = "19.03. 15:00" dt = datetime.strptime(time_str, "%d.%m. %H:%M") # 手动补充赛事年份2024 dt = dt.replace(year=2024)
2. 嵌套分组实现
可以用字典嵌套的方式实现先按Day、再按Championship的分组:
- 外层字典的键是
Day值,值是内层字典 - 内层字典的键是
Championship值,值是该分组下的所有赛事数据列表
3. 时间差计算
两个datetime对象相减会得到timedelta对象,可通过以下属性获取差值:
days:天数seconds:总秒数(可转换为小时/分钟:seconds//3600=小时,(seconds//60)%60=分钟)
完善后的实现代码与思路
from datetime import datetime, timedelta import json def parse_time(time_str, year=2024): """将时间字符串转换为datetime对象,默认使用赛事年份2024""" dt = datetime.strptime(time_str, "%d.%m. %H:%M") # 替换为指定年份 return dt.replace(year=year) # 1. 加载JSON数据 with open('data.json', 'r') as f: file_data = json.load(f) # 2. 实现嵌套分组:Day -> Championship -> 赛事列表 grouped_data = {} for match in file_data: day = match['Day'] championship = match['Matches']['Championship'] # 初始化外层Day键 if day not in grouped_data: grouped_data[day] = {} # 初始化内层Championship键 if championship not in grouped_data[day]: grouped_data[day][championship] = [] # 添加赛事数据,并附带解析后的datetime对象 match_with_dt = match.copy() match_with_dt['Parsed_Time'] = parse_time(match['Matches']['Times']) grouped_data[day][championship].append(match_with_dt) # 3. 计算每组内的时间差 for day, champ_groups in grouped_data.items(): print(f"=== Day: {day} ===") for champ, matches in champ_groups.items(): print(f" Championship: {champ.strip()}") # 至少2场赛事才计算时间差 if len(matches) >= 2: # 按时间排序 sorted_matches = sorted(matches, key=lambda x: x['Parsed_Time']) # 计算相邻赛事的时间差 for i in range(len(sorted_matches)-1): current = sorted_matches[i] next_match = sorted_matches[i+1] diff = next_match['Parsed_Time'] - current['Parsed_Time'] # 格式化输出时间差 days = diff.days hours = diff.seconds // 3600 minutes = (diff.seconds // 60) % 60 print(f" 场次差: {current['Matches']['Home']} vs {current['Matches']['Away']} -> {next_match['Matches']['Home']} vs {next_match['Matches']['Away']}") print(f" 时间差: {days}天 {hours}小时 {minutes}分钟") else: print(" 该分组仅1场赛事,无需计算时间差") print()
代码分步解释
- 时间解析函数:
parse_time统一处理字符串转datetime的逻辑,确保时间格式一致 - 嵌套分组:通过两层字典逐步构建分组结构,每个分组存储带解析后时间的赛事数据
- 时间差计算:对每个分组先按时间排序,再遍历计算相邻赛事的时间差,格式化输出结果
内容的提问来源于stack exchange,提问作者x__SHARINGAN____x
相关产品推荐
相关产品推荐

