如何基于name键过滤列表重复对象,按规则保留目标元素?
问题描述
给定如下对象列表:
[ Phone('name': 'iPhone-14', 'updated_date': '2022-11-12', 'status': 'available'), Phone('name': 'iPhone-14', 'updated_date': '2023-10-12', 'status': 'sold'), Phone('name': 'Samsung-S20', 'updated_date': '2022-10-12', 'status': 'available'), Phone('name': 'Samsung-S20', 'updated_date': '2020-10-12', 'status': 'available'), Phone('name': 'Samsung-S10', 'updated_date': '2020-10-12', 'status': 'sold'), Phone('name': 'iPhone-14', 'updated_date': '2022-04-01', 'status': 'available'), Phone('name': 'Samsung-S10', 'updated_date': '2022-12-11', 'status': 'sold'), ]
需求:针对每个name分组,保留该组中updated_date最新且status为available的对象;若该组无available状态的对象,则保留updated_date最新的对象。
预期处理结果:
[ Phone('name': 'iPhone-14', 'updated_date': '2022-11-12', 'status': 'available'), Phone('name': 'Samsung-S20', 'updated_date': '2022-10-12', 'status': 'available'), Phone('name': 'Samsung-S10', 'updated_date': '2022-12-11', 'status': 'sold'), ]
请问无需多层嵌套循环的最高效实现方式是什么?
高效实现方案
这里提供两种无多层嵌套循环的高效实现方式,适用于不同场景:
方法1:字典跟踪最优项(时间复杂度O(n))
直接遍历所有对象,用字典记录每个name对应的最优对象,遍历过程中实时对比更新,全程只需一次遍历:
from datetime import datetime def get_best_phones(phones): best_map = {} for phone in phones: name = phone.name # 若Phone是字典则用phone['name'] current_date = datetime.strptime(phone.updated_date, '%Y-%m-%d') current_status = phone.status if name not in best_map: best_map[name] = phone continue existing = best_map[name] existing_date = datetime.strptime(existing.updated_date, '%Y-%m-%d') existing_status = existing.status # 优先保留available状态,同状态则选日期最新的 if current_status == 'available': if existing_status != 'available' or current_date > existing_date: best_map[name] = phone else: if existing_status != 'available' and current_date > existing_date: best_map[name] = phone return list(best_map.values())
该方法是线性时间复杂度,数据量越大优势越明显,适合处理大规模数据集。
方法2:排序后分组(时间复杂度O(n log n))
先按规则排序,再用itertools.groupby分组取每组首项,代码更简洁易读:
from itertools import groupby from datetime import datetime def get_best_phones(phones): # 排序规则:按name分组 -> available状态优先 -> 日期倒序(最新在前) def sort_key(phone): date = datetime.strptime(phone.updated_date, '%Y-%m-%d') status_priority = 0 if phone.status == 'available' else 1 return (phone.name, status_priority, -date.timestamp()) sorted_phones = sorted(phones, key=sort_key) # 按name分组后取每组第一个元素 return [next(group) for _, group in groupby(sorted_phones, key=lambda x: x.name)]
该方法代码更紧凑,可读性强,数据量较小时性能足够优秀。
内容的提问来源于stack exchange,提问作者Mikael
相关产品推荐
相关产品推荐

