如何判断difflib.get_close_matches()忽略大小写?我有一个字典,其中包含一个包含大小写的定义格式。但是,测试字符串可能具有完全大小写或没有大小写,这些应该是等效的。但是,结果需要适当地大写,因此我不能使用修改后的字典。
import difflib
names = ['Acacia koa A.Gray var. latifolia (Benth.) H.St.John',
'Acacia koa A.Gray var. waianaeensis H.St.John',
'Acacia koaia Hillebr.',
'Acacia kochii W.Fitzg. ex Ewart & Jean White',
'Acacia kochii W.Fitzg.']
s = 'Acacia kochi W.Fitzg.'
# base case: proper capitalisation
print(difflib.get_close_matches(s,names,1,0.9))
# this should be equivalent from the perspective of my program
print(difflib.get_close_matches(s.upper(),names,1,0.9))
# this won't work because of the dictionary formatting
print(difflib.get_close_matches(s.upper().capitalize(),names,1,0.9))
输出:
['Acacia kochii W.Fitzg.']
[]
[]
工作代码:
根据Hugh Bothwell的回答,我修改了以下代码以获得一个可行的解决方案(当返回多个结果时也应该有效):
import difflib
names = ['Acacia koa A.Gray var. latifolia (Benth.) H.St.John',
'Acacia koa A.Gray var. waianaeensis H.St.John',
'Acacia koaia Hillebr.',
'Acacia kochii W.Fitzg. ex Ewart & Jean White',
'Acacia kochii W.Fitzg.']
test = {n.lower():n for n in names}
s1 = 'Acacia kochi W.Fitzg.' # base case
s2 = 'ACACIA KOCHI W.FITZG.' # test case
results = [test[r] for r in difflib.get_close_matches(s1.lower(),test,1,0.9)]
results += [test[r] for r in difflib.get_close_matches(s2.lower(),test,1,0.9)]
print results
输出:
['Acacia kochii W.Fitzg.', 'Acacia kochii W.Fitzg.']
答案 0 :(得分:8)
我没有看到任何快速方法让difflib做不区分大小写的比较。
快速而肮脏的解决方案似乎是
创建一个将字符串转换为某种规范形式的函数(例如:大写,单行,无标点符号)
使用该函数制作{canonical string:original string}的dict和[canonical string]的列表
针对规范字符串列表运行.get_close_matches,然后通过dict插入结果以获取原始字符串
答案 1 :(得分:0)
经过大量搜索后,我很惊讶地发现没有一个针对此明显用例的简单罐头答案。
唯一的选择似乎是"FuzzyWuzzy" library。但是,它像Python的difflib
一样依赖Levenshtein距离,并且它的API并不是生产质量。它比较模糊的方法的确不区分大小写,但是它不能直接或简单地替换get_close_matches
。
这是我能想到的最简单的实现:
import difflib
def get_close_matches_icase(word, possibilities, *args, **kwargs):
""" Case-insensitive version of difflib.get_close_matches """
lword = word.lower()
lpos = {p.lower(): p for p in possibilities}
lmatches = difflib.get_close_matches(lword, lpos.keys(), *args, **kwargs)
return [lpos[m] for m in lmatches]
答案 2 :(得分:0)
@gatopeich的想法正确,但问题是可能存在许多许多字符串,它们的大小写差异仅 。我们肯定希望它们在结果中 all ,而不仅仅是其中之一!
下面的修改可以做到这一点:
def get_close_matches_icase(word, possibilities, *args, **kwargs):
""" Case-insensitive version of difflib.get_close_matches """
lword = word.lower()
lpos = {}
for p in possibilities:
if p.lower() not in lpos:
lpos[p.lower()] = [p]
else:
lpos[p.lower()].append(p)
lmatches = difflib.get_close_matches(lword, lpos.keys(), *args, **kwargs)
ret = [lpos[m] for m in lmatches]
ret = itertools.chain.from_iterable(ret)
return set(ret)