在Python 2.7中,我想检查一个字符串与列表中的字符串之间的相似性,直到找到匹配为止。
from difflib import SequenceMatcher
def similar(a, b):
return SequenceMatcher(None, a, b).ratio()
correctList = ["thanks", "believe", "definitely"]
myString = "thansk"
for correctWord in correctList:
ratio = similar(correctWord, myString)
if ratio > 0.9:
myString = correctWord
break
print myString
>>> "thanks"
我想将for
迭代简化为更少的行,类似于:
if similar(myString, any([correctWord for correctWord in correctList])) > 0.9:
myString = correctWord
我不完全确定这里的正确逻辑,但在任何一种情况下,此语法的变体都会引发错误:
TypeError :("' bool'对象不可迭代",u'发生在索引0')
实现这一目标的正确方法是什么?
答案 0 :(得分:2)
any
应该只列出一个布尔表达式列表,因此我们需要找到一种方法来首先评估similar
与myString
的每个元素之间的correctList
。我们可以在谓词map
旁边使用lambda s: similar(myString, s) > 0.9
:
any(map(lambda s: similar(s, myString) > 0.9, correctList))
如果True
'中至少有一个元素与correctList
足够相似,则评估结果为myString
。
...但是您会注意到我们要确定 correctList
的哪些元素与myString
类似,所以也许我们应该真正使用{{1 }}:
filter
你可以只取第一个结果,在这种情况下candidates = filter(lambda s: similar(s, myString) > 0.9, correctList)
表达式可以正常工作,但它不一定是最相似的元素next
。
但是,我们可以使用correctList
,map
和filter
来实现这一目标。考虑:
max
返回一对配对列表,每个配对包含一个pairs = map(lambda s: (s, similar(s, myString)), correctList)
元素及其与correctList
的“相似度”。然后,我们可以过滤掉myString
以下相似度的候选人:
0.9
最后我们选择与剩余候选者(使用pairs = filter(lambda (s, d): d > 0.9, pairs)
作为我们的关键函数)具有最大相似度的候选者)或operator.itemgetter
如果不存在:
myString
当然,我们也可以在没有预过滤的情况下使用myString = (max(pairs, key = itemgetter(1)) or [myString])[0]
,如果相似性不足,则忽略答案:
max
答案 1 :(得分:2)
一旦找到具有相似性的第一个字符串>就会停止。 0.9,以"thansk"
作为候选人开始。所以我认为这是等价的:
myString = "thansk"
myString = next((w for w in correctList if similar(w, myString) > 0.9), myString)