Python如何高效对大型列表执行模糊查找及相似排序操作?
相似条目分组效率优化方案
- 基础依赖替换,零改代码提升性能
FuzzyWuzzy默认使用纯Python实现的相似度计算逻辑,性能极低,直接替换为RapidFuzz库即可获得大幅性能提升。该库底层为C++实现,API完全兼容FuzzyWuzzy,仅需修改导入语句:
# 替换原来的fuzzywuzzy导入语句即可 from rapidfuzz.fuzz import token_sort_ratio
仅这一步就能获得5~10倍的性能提升,是成本最低的优化手段。
- 前置过滤规则,减少无效计算
- 长度过滤:两个字符串长度差超过30%时,token_sort_ratio不可能达到70分,对比前先校验长度差,不符合直接跳过,可筛掉80%以上的无效对比
- 维护未处理集合:不要遍历全量列表判断inserted标记,改为维护一个未处理条目集合,每次处理完成后直接移除对应条目,内层循环仅遍历剩余未处理条目,越到后期循环成本越低
优化后代码参考:
def sort_items(): sorted_list = [] unprocessed = set(items) # 初始为全量未处理 total = len(items) while unprocessed: current = unprocessed.pop() sorted_list.append(current) current_len = len(current.name) # 临时列表存本次要移除的相似条目 to_remove = [] for candidate in unprocessed: # 长度差校验,阈值可根据实际相似度要求调整 len_diff = abs(len(candidate.name) - current_len) if len_diff > current_len * 0.3: continue if token_sort_ratio(current.name, candidate.name) >=70: sorted_list.append(candidate) to_remove.append(candidate) # 批量移除已处理的相似条目 for item in to_remove: unprocessed.remove(item) # 进度计算 progress = "{:.2f}".format((total - len(unprocessed))/total *100) print(f"Current Progress: {progress}%", end='\r')
这一步优化后性能可再提升3~5倍。
- 局部敏感哈希分桶,将时间复杂度降至近似O(N)
如果数据量持续增长,可引入n-gram分桶逻辑进一步优化:
- 对每个条目的name先做token排序(和token_sort_ratio的前置处理逻辑一致)
- 将排序后的字符串拆分为固定长度的n-gram(比如3-gram)
- 所有共享至少1个n-gram的条目放入同一个桶
- 仅对同一个桶内的条目做相似度对比
该方案可将对比次数降低2个数量级以上,26500条数据的处理耗时可压缩到10秒以内。
- 可选并行优化
如果还有进一步提速需求,可将分桶后的不同桶分配到不同进程并行计算,因为桶之间没有依赖关系,无锁并行收益极高,不推荐直接对全量数据做并行拆分,会出现跨分片相似条目无法合并的问题。
内容的提问来源于stack exchange,提问作者ryan77627
相关产品推荐
相关产品推荐

