如何高效实现Pydantic对象列表去重,解决现有可用方法速度过慢问题
Pydantic对象列表高效去重方案
首先你遇到的报错和性能问题原因如下:
- 默认的Pydantic BaseModel实例不可哈希,没有实现
__hash__方法,所以直接传入set或者OrderedDict.fromkeys会抛出unhashable type错误 - 你用的
enumerate遍历方法时间复杂度为O(n²),每遍历一个元素都要对比前面所有元素,数据量过万时性能会急剧下降
下面是两种高效的去重方案,时间复杂度均为O(n),万级数据可以秒处理:
方案1:修改模型开启frozen配置,直接用内置方法去重
如果允许修改原Pydantic模型,可以给模型添加frozen配置,让Pydantic自动生成__hash__方法,实例变为可哈希类型,直接用集合或者保序字典去重即可。
修改后的模型代码(a.py):
# Pydantic v2 写法 from pydantic import BaseModel, ConfigDict class Photo(BaseModel): model_config = ConfigDict(frozen=True) title: str url: str
如果使用的是Pydantic v1,配置写法如下:
# Pydantic v1 写法 from pydantic import BaseModel class Photo(BaseModel): title: str url: str class Config: frozen = True
去重代码:
# 不需要保留原始顺序的情况,直接转集合去重 final_list = list(set(pd_obj_list)) # Python 3.7+ 版本dict默认保留插入顺序,需要保序可以用这个写法 final_list_ordered = list(dict.fromkeys(pd_obj_list))
方案2:不修改原模型,手动标记唯一特征去重
如果不希望修改原模型的配置,可以在遍历列表时提取用来判断重复的特征作为唯一标识,用集合记录已出现过的标识,一次遍历完成去重,灵活性更高。
去重代码:
seen = set() final_list = [] for obj in pd_obj_list: # 自定义判重规则,这里用title和url的组合作为唯一标识 unique_key = (obj.title, obj.url) # 如果是全字段判重且字段较多,可以直接用序列化结果作为key # Pydantic v2: unique_key = obj.model_dump_json() # Pydantic v1: unique_key = obj.json() if unique_key not in seen: seen.add(unique_key) final_list.append(obj)
内容的提问来源于stack exchange,提问作者Ig.Foer
相关产品推荐
相关产品推荐

