Python中如何提取两个字符串列表的部分匹配公共元素
解决姓名列表的部分匹配问题
问题描述
有两个姓名列表,需要筛选出第一个列表中在第二个列表里存在部分匹配的姓名(支持姓名顺序颠倒、中间加中间名/缩写/额外姓氏的情况):
list1 = {'ADELA SARABIA', 'JUAN PEREZ', 'JOHN ADAMS', 'TOM HANKS'} list2 = {'JOSE GARCIA', 'HANKS TOM', 'PEREZ LOPEZ JUAN', 'JOHN P. ADAMS'}
期望输出:
matches = {'JUAN PEREZ', 'JOHN ADAMS', 'TOM HANKS'}
你之前使用的代码无法覆盖所有场景,因为它仅检查姓名前缀或前两个词的完整匹配,没法处理姓名顺序颠倒、缩写这类情况。
解决方案
以下代码通过对比姓名拆分后的单词集合,同时处理缩写匹配,完美覆盖你的需求:
def normalize_name(name): # 统一格式:转大写、去掉缩写点号、拆分单词为集合(忽略顺序) words = [word.replace('.', '') for word in name.upper().split()] return set(words) list1 = {'ADELA SARABIA', 'JUAN PEREZ', 'JOHN ADAMS', 'TOM HANKS'} list2 = {'JOSE GARCIA', 'HANKS TOM', 'PEREZ LOPEZ JUAN', 'JOHN P. ADAMS'} matches = set() for name1 in list1: name1_words = normalize_name(name1) # 遍历list2查找匹配项 for name2 in list2: name2_words = normalize_name(name2) # 只要原姓名的所有单词都在目标姓名中出现(不管顺序、中间加词),就算匹配 if name1_words.issubset(name2_words): matches.add(name1) break # 找到匹配后停止检查当前姓名的其他项 print(matches)
代码说明
- normalize_name函数:统一姓名格式,消除大小写、缩写点号的影响,同时将姓名拆分为单词集合,这样可以完全忽略姓名的排列顺序。
- 匹配逻辑:使用集合的
issubset方法,判断原姓名的所有单词是否都在目标姓名的单词集合中——只要满足这个条件,不管中间加了多少额外词、顺序怎么颠倒,都判定为匹配。
运行这段代码后,输出完全符合你的预期:{'JUAN PEREZ', 'JOHN ADAMS', 'TOM HANKS'}
原代码的问题
你之前的代码存在这些明显缺陷:
- 仅检查姓名的第一个单词或前两个词的完整组合,无法处理
TOM HANKS和HANKS TOM这种顺序颠倒的情况。 - 没有处理缩写格式(比如
JOHN ADAMS和JOHN P. ADAMS的匹配场景)。 - 逻辑冗余,还会自动添加
- not found后缀,不符合你只保留匹配项的需求。
内容的提问来源于stack exchange,提问作者Daniela saba rosner
相关产品推荐
相关产品推荐

