Използвайте 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
имате предвид да създадете трети списък, който съдържа елементите, които се появяват както в listA, така и в listB? така че резултатът във вашия случай да бъде['apple', 'orange']
? - person Konsol Labapen   schedule 06.02.2013