如何将字典列表中每个ID的最后两条记录合并为指定格式
解决方法:提取每个ID的倒数第二和最后一条记录时间
我有如下Python列表:
import datetime list1 = [ {'id': 'ABC', 'created_at': datetime.datetime(2024, 8, 1, 11, 22, 3)}, {'id': 'ABC', 'created_at': datetime.datetime(2024, 8, 2, 11, 22, 3)}, {'id': 'ABC', 'created_at': datetime.datetime(2024, 8, 3, 11, 22, 3)}, {'id': 'ABC', 'created_at': datetime.datetime(2024, 8, 5, 11, 22, 3)}, {'id': 'BAC', 'created_at': datetime.datetime(2024, 7, 25, 18, 22, 3)}, {'id': 'BAC', 'created_at': datetime.datetime(2024, 7, 26, 18, 22, 3)}, {'id': 'BAC', 'created_at': datetime.datetime(2024, 8, 1, 18, 22, 3)}, {'id': 'BAC', 'created_at': datetime.datetime(2024, 8, 5, 11, 22, 3)}, {'id': 'CAB', 'created_at': datetime.datetime(2024, 8, 1, 6, 53, 3)}, {'id': 'CAB', 'created_at': datetime.datetime(2024, 8, 1, 17, 53, 3)}, {'id': 'CAB', 'created_at': datetime.datetime(2024, 8, 2, 11, 53, 3)}, {'id': 'CAB', 'created_at': datetime.datetime(2024, 8, 5, 11, 22, 3)}, ]
注:原代码中使用datetime.date传入时分秒参数会报错,这里修正为datetime.datetime以匹配时间格式。
该列表已按id和created_at排序,无需二次排序。
如果每个id仅出现一次,我知道可以这样处理:
output = '\n'.join([f"ID: {l['id']}, Created At: {l['created_at']}" for l in list1])
但我需要生成如下预期输出:
[ {'id': 'ABC', 'start': datetime.datetime(2024, 8, 3, 11, 22, 3), 'end': datetime.datetime(2024, 8, 5, 11, 22, 3)}, {'id': 'BAC', 'start': datetime.datetime(2024, 8, 1, 18, 22, 3), 'end': datetime.datetime(2024, 8, 5, 11, 22, 3)}, {'id': 'CAB', 'start': datetime.datetime(2024, 8, 2, 11, 53, 3), 'end': datetime.datetime(2024, 8, 5, 11, 22, 3)}, ]
需求是:将每个id的倒数第二条记录的日期作为start,最后一条记录的日期作为end。
实现代码
利用itertools.groupby对已排序的列表按id分组,再提取每个分组的倒数第二和最后一条记录的时间:
import datetime from itertools import groupby list1 = [ {'id': 'ABC', 'created_at': datetime.datetime(2024, 8, 1, 11, 22, 3)}, {'id': 'ABC', 'created_at': datetime.datetime(2024, 8, 2, 11, 22, 3)}, {'id': 'ABC', 'created_at': datetime.datetime(2024, 8, 3, 11, 22, 3)}, {'id': 'ABC', 'created_at': datetime.datetime(2024, 8, 5, 11, 22, 3)}, {'id': 'BAC', 'created_at': datetime.datetime(2024, 7, 25, 18, 22, 3)}, {'id': 'BAC', 'created_at': datetime.datetime(2024, 7, 26, 18, 22, 3)}, {'id': 'BAC', 'created_at': datetime.datetime(2024, 8, 1, 18, 22, 3)}, {'id': 'BAC', 'created_at': datetime.datetime(2024, 8, 5, 11, 22, 3)}, {'id': 'CAB', 'created_at': datetime.datetime(2024, 8, 1, 6, 53, 3)}, {'id': 'CAB', 'created_at': datetime.datetime(2024, 8, 1, 17, 53, 3)}, {'id': 'CAB', 'created_at': datetime.datetime(2024, 8, 2, 11, 53, 3)}, {'id': 'CAB', 'created_at': datetime.datetime(2024, 8, 5, 11, 22, 3)}, ] # 按id分组 grouped_records = groupby(list1, key=lambda item: item['id']) result = [] for id_key, records in grouped_records: record_list = list(records) # 取倒数第二条的created_at作为start,最后一条作为end start_time = record_list[-2]['created_at'] end_time = record_list[-1]['created_at'] result.append({'id': id_key, 'start': start_time, 'end': end_time}) # 输出结果 print(result)
代码解释
- 分组:
groupby基于已排序的列表,将相同id的记录归为一组,确保分组的连续性。 - 索引提取:将分组后的迭代器转为列表,通过负索引
-2和-1快速获取倒数第二和最后一条记录的时间。 - 构造结果:将每个
id对应的时间范围封装为字典,添加到结果列表中。
执行代码后即可得到预期的输出结构。
内容的提问来源于stack exchange,提问作者Saeed
相关产品推荐
相关产品推荐

