Python - 匹配来自 2 个列表的字符串
Python - Matching strings from 2 lists
我有 2 个列表。实际和预测。
我需要比较两个列表并确定模糊匹配的数量。我之所以说模糊匹配是因为它们不会完全相同。我正在使用 difflib 库中的 SequenceMatcher。
def similar(a, b):
return SequenceMatcher(None, a, b).ratio()
我可以假设匹配百分比超过 80% 的字符串被认为是相同的。示例列表
actual=[ "Appl", "Orange", "Ornge", "Peace"]
predicted=["Red", "Apple", "Green", "Peace", "Orange"]
我需要一种方法来找出预测列表中的Apple、Peace 和Orange 是否已在实际列表中找到。所以只进行了 3 场比赛,而不是 5 场比赛。
我如何有效地做到这一点?
>>> actual=["Apple", "Appl", "Orange", "Ornge", "Peace"]
>>> predicted=["Red", "Apple", "Green", "Peace", "Orange"]
>>> set(actual) & set(predicted)
set(['Orange', 'Peace', 'Apple'])
您可以将两个列表都转换为集合并在它们上应用交集。
这会给你三个项目 {'Peace', 'Apple', 'Orange'}
。
然后,你可以计算结果集内的len与实际列表len的比值。
actual=["Apple", "Appl", "Orange", "Ornge", "Peace"]
predicted=["Red", "Apple", "Green", "Peace", "Orange"]
res = set(actual).intersection(predicted)
print (res)
print ((len(res) / len(actual)) * 100)
编辑:
为了使用比率,您需要实现嵌套循环。
由于 set 是作为散列 table 实现的,所以搜索是 O(1),我更愿意使用实际作为 set。
如果预测与实际(完全匹配)相符,那么只需将其添加到您的结果集中即可。 (最好的情况是所有这些都是这样,最终的复杂度是 O(n))。
如果预测与实际不符,则循环遍历实际,看看是否存在大于0.8的比率。 (最坏的情况是所有的都这样,复杂度(On^2))
actual={"Appl", "Orange", "Ornge", "Peace"}
predicted=["Red", "Apple", "Green", "Peace", "Orange"]
result = {}
for pre in predicted:
if pre in actual:
result.add(pre)
else:
for act in actual:
if (similar(pre, act) > 0.8):
result.add(pre)
如果模糊匹配确实是您要查找的内容,您可以使用以下集合推导式通过 similar
方法获得所需的输出。
threshold = 0.8
result = {x for x in predicted for y in actual if similar(x, y) > threshold}
在这种情况下,您只需检查预测列表中的第 i 个元素是否存在于实际列表中。
如果存在,则添加到新列表。
In [2]: actual=["Apple", "Appl", "Orange", "Ornge", "Peace"]
...: predicted=["Red", "Apple", "Green", "Peace", "Orange"]
In [3]: [i for i in predicted if i in actual]
Out[3]: ['Apple', 'Peace', 'Orange']
简单但无效的方法是:
counter = 0
for item in b:
if SequenceMatcher(None, a, item).ratio() > 0:
counter += 1
这就是您想要的,模糊匹配元素的数量,而不仅仅是相同元素(大多数其他答案都提供)。
{x[1] for x in itertools.product(actual, predicted) if similar(*x) > 0.80}
先取两组的交集:
actual, predicted = set(actual), set(predicted)
exact = actual.intersection(predicted)
如果这包括您所有的实际单词,那么您就完成了。然而,
if len(exact) < len(actual):
fuzzy = [word for word in actual-predicted for match in predicted if similar(word, match)>0.8]
最后你的结果集是 exact.union(set(fuzzy))
您也可以尝试以下方法来达到您的要求:
import itertools
fuzlist = [ "Appl", "Orange", "Ornge", "Peace"]
actlist = ["Red", "Apple", "Green", "Peace", "Orange"]
foundlist = []
for fuzname in fuzlist:
for name in actlist:
for actname in itertools.permutations(name):
if fuzname.lower() in ''.join(actname).lower():
foundlist.append(name)
break
print set(foundlist)
我有 2 个列表。实际和预测。 我需要比较两个列表并确定模糊匹配的数量。我之所以说模糊匹配是因为它们不会完全相同。我正在使用 difflib 库中的 SequenceMatcher。
def similar(a, b):
return SequenceMatcher(None, a, b).ratio()
我可以假设匹配百分比超过 80% 的字符串被认为是相同的。示例列表
actual=[ "Appl", "Orange", "Ornge", "Peace"]
predicted=["Red", "Apple", "Green", "Peace", "Orange"]
我需要一种方法来找出预测列表中的Apple、Peace 和Orange 是否已在实际列表中找到。所以只进行了 3 场比赛,而不是 5 场比赛。 我如何有效地做到这一点?
>>> actual=["Apple", "Appl", "Orange", "Ornge", "Peace"]
>>> predicted=["Red", "Apple", "Green", "Peace", "Orange"]
>>> set(actual) & set(predicted)
set(['Orange', 'Peace', 'Apple'])
您可以将两个列表都转换为集合并在它们上应用交集。
这会给你三个项目 {'Peace', 'Apple', 'Orange'}
。
然后,你可以计算结果集内的len与实际列表len的比值。
actual=["Apple", "Appl", "Orange", "Ornge", "Peace"]
predicted=["Red", "Apple", "Green", "Peace", "Orange"]
res = set(actual).intersection(predicted)
print (res)
print ((len(res) / len(actual)) * 100)
编辑:
为了使用比率,您需要实现嵌套循环。 由于 set 是作为散列 table 实现的,所以搜索是 O(1),我更愿意使用实际作为 set。
如果预测与实际(完全匹配)相符,那么只需将其添加到您的结果集中即可。 (最好的情况是所有这些都是这样,最终的复杂度是 O(n))。
如果预测与实际不符,则循环遍历实际,看看是否存在大于0.8的比率。 (最坏的情况是所有的都这样,复杂度(On^2))
actual={"Appl", "Orange", "Ornge", "Peace"}
predicted=["Red", "Apple", "Green", "Peace", "Orange"]
result = {}
for pre in predicted:
if pre in actual:
result.add(pre)
else:
for act in actual:
if (similar(pre, act) > 0.8):
result.add(pre)
如果模糊匹配确实是您要查找的内容,您可以使用以下集合推导式通过 similar
方法获得所需的输出。
threshold = 0.8
result = {x for x in predicted for y in actual if similar(x, y) > threshold}
在这种情况下,您只需检查预测列表中的第 i 个元素是否存在于实际列表中。 如果存在,则添加到新列表。
In [2]: actual=["Apple", "Appl", "Orange", "Ornge", "Peace"]
...: predicted=["Red", "Apple", "Green", "Peace", "Orange"]
In [3]: [i for i in predicted if i in actual]
Out[3]: ['Apple', 'Peace', 'Orange']
简单但无效的方法是:
counter = 0
for item in b:
if SequenceMatcher(None, a, item).ratio() > 0:
counter += 1
这就是您想要的,模糊匹配元素的数量,而不仅仅是相同元素(大多数其他答案都提供)。
{x[1] for x in itertools.product(actual, predicted) if similar(*x) > 0.80}
先取两组的交集:
actual, predicted = set(actual), set(predicted)
exact = actual.intersection(predicted)
如果这包括您所有的实际单词,那么您就完成了。然而,
if len(exact) < len(actual):
fuzzy = [word for word in actual-predicted for match in predicted if similar(word, match)>0.8]
最后你的结果集是 exact.union(set(fuzzy))
您也可以尝试以下方法来达到您的要求:
import itertools
fuzlist = [ "Appl", "Orange", "Ornge", "Peace"]
actlist = ["Red", "Apple", "Green", "Peace", "Orange"]
foundlist = []
for fuzname in fuzlist:
for name in actlist:
for actname in itertools.permutations(name):
if fuzname.lower() in ''.join(actname).lower():
foundlist.append(name)
break
print set(foundlist)