Возможно, используйте collections.Counter()
; это мультимножества или пакеты, на языке типов данных:
from collections import Counter
counterA = Counter(listA)
counterB = Counter(listB)
Теперь вы можете сравнить их по записям или частотам:
>>> counterA
Counter({'apple': 3, 'orange': 2, 'banana': 1})
>>> counterB
Counter({'apple': 2, 'orange': 1, 'grapefruit': 1})
>>> counterA - counterB
Counter({'orange': 1, 'apple': 1, 'banana': 1})
>>> counterB - counterA
Counter({'grapefruit': 1})
Вы можете вычислить их косинусное сходство, используя:
import math
def counter_cosine_similarity(c1, c2):
terms = set(c1).union(c2)
dotprod = sum(c1.get(k, 0) * c2.get(k, 0) for k in terms)
magA = math.sqrt(sum(c1.get(k, 0)**2 for k in terms))
magB = math.sqrt(sum(c2.get(k, 0)**2 for k in terms))
return dotprod / (magA * magB)
Который дает:
>>> counter_cosine_similarity(counterA, counterB)
0.8728715609439696
Чем ближе к 1 это значение, тем больше похожи два списка.
Косинусное сходство — это одна оценка, которую вы можете рассчитать. Если вам важна длина списка, вы можете вычислить другой; если вы сохраните эту оценку между 0,0 и 1,0, вы можете перемножить два значения для окончательной оценки между -1,0 и 1,0.
Например, чтобы учесть относительную длину, вы можете использовать:
def length_similarity(c1, c2):
lenc1 = sum(c1.itervalues())
lenc2 = sum(c2.itervalues())
return min(lenc1, lenc2) / float(max(lenc1, lenc2))
а затем объединить в функцию, которая принимает списки в качестве входных данных:
def similarity_score(l1, l2):
c1, c2 = Counter(l1), Counter(l2)
return length_similarity(c1, c2) * counter_cosine_similarity(c1, c2)
Для ваших двух примеров списков это приводит к:
>>> similarity_score(['apple', 'orange', 'apple', 'apple', 'banana', 'orange'], ['apple', 'orange', 'grapefruit', 'apple'])
0.5819143739626463
>>> similarity_score(['apple', 'apple', 'orange', 'orange'], ['apple', 'orange'])
0.4999999999999999
При необходимости вы можете смешивать другие показатели.
person
Martijn Pieters
schedule
06.02.2013
similarity
вы подразумеваете создание третьего списка, содержащего элементы, которые появляются как в списке A, так и в списке B? чтобы результат в вашем случае был['apple', 'orange']
? - person Konsol Labapen   schedule 06.02.2013