我正在尝试搜索列表(DB)以查找文本片段的可能匹配项。例如,我有一个带有文本“邪恶者”的数据库。我想使用用户输入来搜索数据库中的任何可能的匹配,并给出答案。如果用户输入“hello”,则没有可能的匹配。如果用户输入“evil”,那么可能的匹配是邪恶的,信心为57%(7个字母中有4个匹配),依此类推。
但是,我还想要一种匹配输入文本的方法,例如“evxxman”。 evxxman的7个字符中的5个与DB中的文本“evilman”匹配。但是python中的简单检查会说没有匹配,因为它只输出连续匹配的文本。我希望这是有道理的。感谢
以下是我的代码:
db = []
possible_signs = []
db.append("evilman")
text = raw_input()
for s in db:
if text in s:
if len(text) >= len(s)/2:
possible_signs.append(s)
count += 1
confidence = (float(len(text)) / float(len(s))) * 100
print "Confidence:", '%.2f' %(confidence), "<possible match:>", possible_signs[0]
答案 0 :(得分:1)
要查找质量评估的匹配项,请查看difflib.SequenceMatcher.ratio和朋友 - 这些功能可能不是最快的匹配检查程序,但它们很容易使用。
从difflib docs复制的示例
>>> s = SequenceMatcher(None, "abcd", "bcde")
>>> s.ratio()
0.75
>>> s.quick_ratio()
0.75
>>> s.real_quick_ratio()
1.0
答案 1 :(得分:1)
根据您的描述和示例,在我看来,您实际上正在寻找类似Levenshtein (or edit) distance的内容。请注意,它并没有给出你指定的分数,但我认为它给出了你真正想要的分数。
有几个包有效地实现了这一点,例如distance
:
In [1]: import distance
In [2]: distance.levenshtein('evilman', 'hello')
Out[2]: 6L
In [3]: distance.levenshtein('evilman', 'evil')
Out[3]: 3L
In [4]: distance.levenshtein('evilman', 'evxxman')
Out[4]: 2L
请注意,该库包含多个相似度量,例如,jaccard和sorensen默认返回标准化值:
>>> distance.sorensen("decide", "resize")
0.5555555555555556
>>> distance.jaccard("decide", "resize")
0.7142857142857143
答案 2 :(得分:1)
创建一个while循环并跟踪两个迭代器,一个用于关键字(“evil”),另一个用于查询词(“evilman”)。这是一些伪代码:
key = "evil"
query = "evilman"
key_iterator = 0
query_iterator = 0
confidence_score = 0
while( key_iterator < key.length && query_iterator < query.length ) {
if (key[key_iterator] == query[query_iterator]) {
confidence_score++
key_iterator++
}
query_iterator++
}
// If we didnt reach the end of the key
if (key_iterator != key.length) {
confidence_score = 0
}
print ("Confidence: " + confidence_score + " out of " + query.length)
答案 3 :(得分:1)
这第一个版本似乎符合您的例子。它使字符串&#34;滑动&#34;相互对立,并计算相同字符的数量。 通过将字符数除以参考字符串长度来进行比率。添加最大值和瞧。 为数据库中的每个字符串调用它。
def commonChars(txt, ref):
txtLen = len(txt)
refLen = len(ref)
r = 0
for i in range(refLen + (txtLen - 1)):
rStart = abs(min(0, txtLen - i - 1))
tStart = txtLen -i - 1 if i < txtLen else 0
l = min(txtLen - tStart, refLen - rStart)
c = 0
for j in range(l):
if txt[tStart + j] == ref[rStart + j]:
c += 1
r = max(r, c / refLen)
return r
print(commonChars('evxxman', 'evilman')) # 0.7142857142857143
print(commonChars('evil', 'evilman')) # 0.5714285714285714
print(commonChars('man', 'evilman')) # 0.42857142857142855
print(commonChars('batman', 'evilman')) # 0.42857142857142855
print(commonChars('batman', 'man')) # 1.0
第二个版本产生相同的结果,但使用其他答案中提到的difflib。 它计算匹配块,求和它们的长度,并根据参考长度计算比率。
import difflib
def commonBlocks(txt, ref):
matcher = difflib.SequenceMatcher(a=txt, b=ref)
matchingBlocks = matcher.get_matching_blocks()
matchingCount = sum([b.size for b in matchingBlocks])
return matchingCount / len(ref)
print(commonBlocks('evxxman', 'evilman')) # 0.7142857142857143
print(commonBlocks('evxxxxman', 'evilman')) # 0.7142857142857143
如上面的调用所示,行为略有不同。 &#34;孔&#34;忽略匹配块之间,并且不改变最终比率。