Python按字典列表指定键最大值筛选并保留完整字典
问题需求
需要对字典列表进行筛选,保留每个JobName对应的StartedOn值最大的完整字典。现有代码仅能筛选出对应键值,无法保留完整字典结构。
现有代码
final_list = [] jobs = [glue_client.job_status(e) for e in j] for e in jobs: for page in e: final_list.append(page["JobRuns"]) flat_list = [item for sublist in final_list for item in sublist] sorted_list = sorted(flat_list, key=lambda k: (k['JobName'], k['StartedOn']), reverse=True) # 需要保留的键:"JobName", "JobRunState", "StartedOn" 和 "Id" latest_jobs = [ {'JobName': key, 'StartedOn': max(item['StartedOn'] for item in values)} for key, values in groupby(flat_list, lambda dct: dct['JobName']) ] print(latest_jobs)
数据样例
sorted_list对应的数据集:
list_of_dicts = [ {'JobName': 'a', 'StartedOn': datetime.datetime(2022, 10, 18, 13, 0, 47, 306000, tzinfo=tzlocal()), 'JobRunState': 'fail', 'id': 'xyz'}, {'JobName': 'a', 'StartedOn': datetime.datetime(2021, 10, 18, 13, 0, 47, 306000, tzinfo=tzlocal()), 'JobRunState': 'ok', 'id': 'xyz'}, {'JobName': 'b', 'StartedOn': datetime.datetime(2022, 10, 18, 13, 0, 47, 306000, tzinfo=tzlocal()), 'JobRunState': 'fail', 'id': 'xyz'}, {'JobName': 'a', 'StartedOn': datetime.datetime(2020, 10, 18, 13, 0, 47, 306000, tzinfo=tzlocal()), 'JobRunState': 'fai;', 'id': 'xyz'}, {'JobName': 'b', 'StartedOn': datetime.datetime(2021, 10, 18, 13, 0, 47, 306000, tzinfo=tzlocal()), 'JobRunState': 'ok', 'id': 'xyz'} ]
预期输出
filtered_list = [ {'JobName': 'a', 'StartedOn': datetime.datetime(2022, 10, 18, 13, 0, 47, 306000, tzinfo=tzlocal()), 'JobRunState': 'fail', 'id': 'xyz'}, {'JobName': 'b', 'StartedOn': datetime.datetime(2022, 10, 18, 13, 0, 47, 306000, tzinfo=tzlocal()), 'JobRunState': 'fail', 'id': 'xyz'} ]
解决方案
方法一:利用已排序列表结合groupby
你已经对列表按JobName和StartedOn降序排序,groupby会把相同JobName的项聚合在一起,每组的第一个元素就是StartedOn最大的完整字典,直接取第一个即可:
from itertools import groupby # groupby要求输入列表按分组键排序,此处sorted_list已满足条件 latest_jobs = [next(values) for key, values in groupby(sorted_list, lambda dct: dct['JobName'])]
方法二:遍历记录最新项
如果不想依赖排序,可遍历所有项,用字典记录每个JobName对应的最新(StartedOn最大)完整字典:
latest_jobs_dict = {} for job in flat_list: job_name = job['JobName'] # 若当前JobName未记录,或当前项的StartedOn比已记录的更新 if job_name not in latest_jobs_dict or job['StartedOn'] > latest_jobs_dict[job_name]['StartedOn']: latest_jobs_dict[job_name] = job # 将字典值转为列表即得预期结果 latest_jobs = list(latest_jobs_dict.values())
说明
- 方法一依托已完成的排序操作,代码简洁高效;
- 方法二无需排序,仅遍历一次即可完成,时间复杂度O(n),更适合大数据量场景。
内容的提问来源于stack exchange,提问作者marcin2x4
相关产品推荐
相关产品推荐

