如何实现列表间前缀模糊匹配并区分匹配与未找到项
前缀模糊匹配问题修复
需求说明
对to_search列表中的每个值,在choices列表中执行严格前缀模糊匹配(仅认可前缀顺序完全一致的匹配),返回result列表中对应的项;无匹配项时显示NOT FOUND。
原代码问题
原代码使用rapidfuzz的process.extractOne和fuzz.WRatio,存在两个核心问题:
- 误匹配:例如
38050被错误匹配到358,不符合前缀匹配要求 - 未匹配项标识错误:例如
49185、51078错误匹配到1,未返回NOT FOUND
原代码:
from rapidfuzz import process, fuzz choices = [ '237','1721','124622','334','124624','124','1246','1876','358', '33751','33679','599','61','230','31','65','1721','1','124623' ] result = [ 'NAD','ATE','STA','SSI','GYP','RIC','EEC','AND','GIU','ANC', 'PAI','GAR','TAL','ANI','LAN','TRI','GDO','MAR','EDE' ] to_search = ['18763044','187635','23092','3162','38050','33','49185','51078','1246','1721'] for element in to_search: match = process.extractOne(element, choices, scorer=fuzz.WRatio) print(element,result[match[2]],' ## ',match)
当前错误输出
18763044 AND ## ('1876', 90.0, 7) 187635 AND ## ('1876', 90.0, 7) 23092 ANI ## ('230', 90.0, 13) 3162 LAN ## ('31', 90.0, 14) 38050 GIU ## ('358', 72.0, 8) // 应标记为NOT FOUND 33 SSI ## ('334', 90.0, 3) 49185 MAR ## ('1', 90.0, 17) // 应标记为NOT FOUND 51078 MAR ## ('1', 90.0, 17) // 应标记为NOT FOUND 1246 EEC ## ('1246', 100.0, 6) 1721 ATE ## ('1721', 100.0, 1)
解决方案
要实现严格前缀匹配,需自定义评分规则并设置匹配阈值:
- 自定义评分函数,仅当
choice是element的前缀时计算有效分数,否则返回0 - 设置分数阈值,低于阈值时判定为无匹配
修改后的代码:
from rapidfuzz import process, fuzz choices = [ '237','1721','124622','334','124624','124','1246','1876','358', '33751','33679','599','61','230','31','65','1721','1','124623' ] result = [ 'NAD','ATE','STA','SSI','GYP','RIC','EEC','AND','GIU','ANC', 'PAI','GAR','TAL','ANI','LAN','TRI','GDO','MAR','EDE' ] to_search = ['18763044','187635','23092','3162','38050','33','49185','51078','1246','1721'] def prefix_scorer(query, choice, **kwargs): # 仅当choice是query的前缀时计算分数,否则返回0 if query.startswith(choice): return fuzz.WRatio(query, choice) return 0 for element in to_search: match = process.extractOne(element, choices, scorer=prefix_scorer, score_cutoff=80) if match: print(element, result[match[2]]) else: print(element, "NOT FOUND")
代码解释
prefix_scorer函数:从根源上过滤非前缀匹配,仅当choice是query的前缀时才计算匹配分数score_cutoff=80:过滤低质量匹配,无有效匹配时match为None,此时输出NOT FOUND
最终输出
18763044 AND 187635 AND 23092 ANI 3162 LAN 38050 NOT FOUND 33 SSI 49185 NOT FOUND 51078 NOT FOUND 1246 EEC 1721 ATE
内容的提问来源于stack exchange,提问作者Rasec Malkic
相关产品推荐
相关产品推荐

