我有一个列表:list = ['item1', 'item2', 'item3', 'item4']
我想比较所有项目的相似性。
如果item2
和item3
相似,则结果为list = ['item1', 'item2', 'item4']
编辑:
对不起我的疑惑。
列表项是三元组的集合。我想删除列表中的类似项目。
list = [('very','beauty','place'),('very','good','place'),('another','trigram','item')]
具有计算jaccard相似性,该列表中的每个对项,如果对项的jaccard得分> 0.4,我称之为相似。在此示例中,item1和item2类似。我想要的最后一个输出是:
list = [('very','beauty','place'),('another','trigram','item')]
这是计算jaccard分数的方法:
def compute_jaccard_index(set_1, set_2):
n = len(set_1.intersection(set_2))
return n / float(len(set_1) + len(set_2) - n)
答案 0 :(得分:2)
如果这些项目是字符串或数字,那么您正在寻找内置集合。
例如:
In [1]: foo = [1, 32, 4, 5, 6, 5]
In [2]: set(foo)
Out[2]: {1, 4, 5, 6, 32}
In [3]: list(set(foo))
Out[3]: [32, 1, 4, 5, 6]
真正取决于你的意思。
答案 1 :(得分:1)
如果你有一个相似性函数而不是直接的相等比较,这将有效:
itemsToRemove = []
n = len(list)
for i in range(n):
for j in range(i+1,n):
if(similarTest(list[i], list[j]):
itemsToRemove.append(list[i])
break
return [item for item in list if item not in itemsToRemove]
当然,如果您实际上想要删除相同的项目,正如其他人所建议的那样,那么套装将会很有效。
答案 2 :(得分:1)
此解决方案将继续查看两个元素的对,直到它查看所有对而不过滤任何对。这不是一个有效的解决方案,因为它将一遍又一遍地继续查看相同的对,并且它也没有利用可能的传递性。但这是一个开始。
>>> from itertools import combinations
>>> def filterSimilar (d):
while True:
filteredOne = False
for s, t in combinations(d, 2):
if isSimilar(s, t):
d.remove(t)
filteredOne = True
break
if not filteredOne:
break
>>> d = ['asdf', 'asxf', 'foo', 'bar', 'baz']
>>> filterSimilar(d)
>>> d
['asdf', 'foo', 'bar']
isSimilar
的一个可能的示例实现如下,它使用两个字符串之间的Levenshtein距离:
def levenshteinDistance (s, t):
if len(s) == 0:
return len(t)
if len(t) == 0:
return len(s)
return min(levenshteinDistance(s[:-1], t) + 1, levenshteinDistance(s, t[:-1]) + 1, levenshteinDistance(s[:-1], t[:-1]) + (0 if s[-1] == t[-1] else 1))
def isSimilar (s, t):
return levenshteinDistance(s, t) < 2
(请注意,我在此示例中使用的Levenshtein距离不是传递性比较的示例)
使用compute_jaccard_index
功能,isSimilar
功能现在如下所示:
def isSimilar (s, t):
return compute_jaccard_index(s, t) > .4
然后用于您的示例数据:
>>> lst = [{'very','beauty','place'},{'very','good','place'},{'another','trigram','item'}]
>>> filterSimilar(lst)
>>> lst
[{'very', 'beauty', 'place'}, {'item', 'trigram', 'another'}]
答案 3 :(得分:0)
您可以使用set
。它会从列表中删除所有重复元素。
>>>list = [1,2,3,4,4,5,2,3,1]
>>>list =set(list)
>>>list
set([1, 2, 3, 4, 5])