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(模式,字符串)

+0

谢谢你,我这样做,并没有工作:进口重新 模式=“奥巴马” 匹配= re.findall(模式,“会员数据REWNEW:EX支付ID:234242巴拉克·侯赛因·奥巴马华盛顿特区LAST CO 2834298:EExe类似:00WIE“) –

+0

你传入的字符串之间有侯赛因,所以这就是为什么没有找到匹配。你可以对每个单词进行搜索,并检查是否有两个单词。 例如: 如果re.search(“巴拉克,字符串),并重新 搜索(”奥巴马”,字符串): 做一些 – user8659364

+0

你的字符串中有侯赛因在美国总统奥巴马因此&放大器之间;#39; S不匹配。试试这个: if re.search('Barack',string)和re.search('Obama',string): 做些什么 – user8659364

最简单的方法将只是检查的名字及姓氏。在你的例子中,你可以这样做:

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 

这应该允许您比较较长文本与较短文本匹配的模糊分数。一旦你想开始将搜索条件与目标字符串中不同大小的片段进行匹配,它会变得更加复杂,但是你应该在那个时候查看正则表达式(我想我会提供更多可能的解决方案)。

+0

谢谢Rach Sarp。超级有用。我加入了原文。请看我的评论。谢谢。 –