python:在另一个字符串中查找名称的最佳方法
我正在处理来自多个来源的一些聚合成员资格数据。我在一列中有名字,在另一列中有长成员资格备忘录字符串。我想最好的方式来匹配名称成员资格备忘录。python:在另一个字符串中查找名称的最佳方法
例如,
我想最好的方式找到:
'Barack Obama'
在下列字符串
,由于该数据汇总和格式可能会有所不同。这里有几个例子:
"Member Data REWNEW:EX PAID ID:234242 Barack Obama WASHINGTON DC LAST CO 2834298:EEXE:00WIE"
"Member Data REWNEW:EX PAID ID:234242 Barack Hussein Obama WASHINGTON DC LAST CO 2834298:EEXE:00WIE"
"Member Data REWNEW:EX PAID ID:234242 Obama Barack WASHINGTON DC LAST CO 2834298:EEXE:00WIE"
"Member Data REWNEW:EX PAID ID:234242 Barack H Obama WASHINGTON DC LAST CO 2834298:EEXE:00WIE"
在过去,我用fuzzywuzzy做模糊逻辑匹配。如果我正在比较两个字符串,但这并不试图在另一个较长的字符串中找到一个字符串,这往往会工作得很好。例如:
from fuzzywuzzy import fuzz
from fuzzywuzzy import fuzz
print(fuzz.ratio("Barack Obama", "Barack Obama"))
print(fuzz.ratio("Michelle Obama", "Barack Obama"))
print(fuzz.ratio("Barack Obama", "Member Data REWNEW:EX PAID ID:234242 Barack Hussein Obama WASHINGTON DC LAST CO 2834298:EEXE:00WIE"))
print(fuzz.ratio("Michelle Obama", "Member Data REWNEW:EX PAID ID:234242 Barack Hussein Obama WASHINGTON DC LAST CO 2834298:EEXE:00WIE"))
100
54
22
16
这是非常清楚的是,前两个是非常不同的(100:54),然而在第二两不似乎是所有不同的,因此这不是最佳方法。
有没有人有关于如何最好地实现这种类型的字符串搜索的任何想法?
非常感谢!
UPDATE1:
我想:
memo_string="Member Data REWNEW:EX PAID ID:234242 Barack Hussein Obama WASHINGTON DC LAST CO 2834298:EEXE:00WIE"
search_terms = "Barack Obama"
memo_words = memo_string.split(" ")
search_term_count = len(search_terms.split(" "))
memo_slices = []
for i in range(len(memo_words) - search_term_count):
memo_slices.append(" ".join(memo_words[i:i+search_term_count]))
max_for_memo = 0
best_match_in_memo = None
for memo_slice in memo_slices:
fuzz_score = fuzz.ratio(search_terms, memo_slice)
if fuzz_score > max_for_memo:
max_for_memo = fuzz_score
best_match_in_memo = memo_slice
print(max_for_memo)
I also tried with search_terms = 'Michelle Obama'
两个评分分别为52和50,这仍然存在,我在开头所述的挑战,这是我想某种的逻辑将两者更明确地区分开来。
想法?
非常感谢!
使用findall或从re模块搜索。 Findall返回匹配字符串的列表。如果找到匹配,搜索返回true。 例如: 进口重新 模式=“奥巴马” 匹配= re.findall(模式,字符串)
最简单的方法将只是检查的名字及姓氏。在你的例子中,你可以这样做:
search_terms = "Barack Obama"
matches = []
for memo_string in memos_list:
for word in search_terms.split(" "):
if word not in memo_string:
break
else:
matches.append(memo_string) # triggers when the for loop doesn't break
这将匹配包含您的确切搜索条件的所有备忘录。尽管如此,这并不检查术语是否彼此相邻并要求它们完全匹配。
对于较模糊的匹配,您可以将您的搜索条件与备忘录字符串的切片进行比较(为简洁起见,某些前导码被省略)。
memo_words = memo_string.split(" ")
search_term_count = len(search_terms.split(" "))
memo_slices = []
for i in range(memo_words - search_term_count):
memo_slices.append(" ".join(memo_words[i:i+search_term_count]))
max_for_memo = 0
best_match_in_memo = None
for memo_slice in memo_slices:
fuzz_score = fuzz.ratio(search_terms, memo_slice)
if fuzz_score > max_for_memo:
max_for_memo = fuzz_score
best_match_in_memo = memo_slice
这应该允许您比较较长文本与较短文本匹配的模糊分数。一旦你想开始将搜索条件与目标字符串中不同大小的片段进行匹配,它会变得更加复杂,但是你应该在那个时候查看正则表达式(我想我会提供更多可能的解决方案)。
谢谢Rach Sarp。超级有用。我加入了原文。请看我的评论。谢谢。 –
谢谢你,我这样做,并没有工作:进口重新 模式=“奥巴马” 匹配= re.findall(模式,“会员数据REWNEW:EX支付ID:234242巴拉克·侯赛因·奥巴马华盛顿特区LAST CO 2834298:EExe类似:00WIE“) –
你传入的字符串之间有侯赛因,所以这就是为什么没有找到匹配。你可以对每个单词进行搜索,并检查是否有两个单词。 例如: 如果re.search(“巴拉克,字符串),并重新 搜索(”奥巴马”,字符串): 做一些 – user8659364
你的字符串中有侯赛因在美国总统奥巴马因此&放大器之间;#39; S不匹配。试试这个: if re.search('Barack',string)和re.search('Obama',string): 做些什么 – user8659364