2015-04-28 4 views
6

Это скорее математическая проблема, чем что-либо еще. Давайте предположим, у меня есть два списка разных размеров в PythonПроцентное перекрытие двух списков

listA = ["Alice", "Bob", "Joe"] 
listB = ["Joe", "Bob", "Alice", "Ken"] 

Я хочу, чтобы выяснить, какой процент пересекаться эти два списка есть. Заказ не важен в списках. Найти совпадение легко, я видел другие сообщения о том, как это сделать, но я не могу его полностью расширить, чтобы выяснить, какой процент они перекрывают. Если бы я сравнил списки в разных порядках, результат получился бы иначе? Какой был бы лучший способ сделать это?

+0

Порядок здесь не имеет большого значения. Однако сначала вам нужно определить формулу для процента, это может быть что-то вроде: '2 * количество совпадений/(len (lista) + len (listb))' или что-то еще – ZdaR

+1

Что делать, если lis ts - '[1,1,1]' и '[1]'. Будет ли перекрытие на 100% или 33%? –

+0

Каков ожидаемый результат для этих двух списков? – Ofiris

ответ

4

Максимальное различие заключается в том, что два списка имеют совершенно разные элементы. Таким образом, мы имеем не более n + m дискретных элементов, где n - размер первого списка, а m - размер второго списка. Одной из мер может быть:

2 * c/(n + m) 

, где c это количество общих элементов. Это может быть вычислена, как это в процентах:

200.0 * len(set(listA) & set(listB))/(len(listA) + len(listB)) 
+0

Это не подходит для следующего примера: listA = ["Алиса", "Алиса"] listB = ["Алиса", "Алиса"] –

2
>>> len(set(listA)&set(listB))/float(len(set(listA) | set(listB))) * 100 
75.0 

Я бы рассчитать общие элементы из общего числа различных элементов.

len(set(listA)&set(listB)) возвращает общие предметы (3 в вашем примере).

len(set(listA) | set(listB)) возвращает общее количество отдельных предметов (4).

Умножьте на 100 и получите процент.

+0

Обратите внимание, что этот ответ и ответ @JuniorCompressor отличаются, оба правильные, но зависят от специфическое требование. – Ofiris

2

С главной точки зрения, я бы сказал, что есть два разумных вопросы, вы можете спросить:

  1. Какой процент перекрытие, если по сравнению с первым списком? То есть насколько велика общая часть по сравнению с первым списком?
  2. То же самое для второго списка.
  3. Какой процент перекрывается по сравнению с «вселенной» (т. Е. Объединение обоих списков)?

Также можно найти другие значения, и их было бы много. В общем, вы, вероятно, должны знать, какую проблему вы пытаетесь решить.

С программированием точки зрения, решение легко:

listA = ["Alice", "Bob", "Joe"] 
listB = ["Joe", "Bob", "Alice", "Ken"] 

setA = set(listA) 
setB = set(listB) 

overlap = setA & setB 
universe = setA | setB 

result1 = float(len(overlap))/len(setA) * 100 
result2 = float(len(overlap))/len(setB) * 100 
result3 = float(len(overlap))/len(universe) * 100 
0
def computeOverlap(L1, L2): 
    d1, d2 = {}, {} 
    for e in L1: 
     if e not in d1: 
      d1[e] = 1 
     d1[e] += 1 

    for e in L2: 
     if e not in d2: 
      d2[e] = 0 
     d2[e] += 1 

    o1, o2 = 0, 0 
    for k in d1: 
     o1 += min(d1[k], d2.get(k,0)) 
    for k in d2: 
     o2 += min(d1.get(k,0), d2[k]) 

    print((100*o1) if o1 else 0 "% of the first list overlaps with the second list") 
    print((100*o2) if o2 else 0 "% of the second list overlaps with the first list") 

Конечно, вы можете просто сделать это с defaultdict и счетчиком, чтобы сделать вещи немного проще:

from collections import defaultdict, Counter 

def computeOverlap(L1, L2): 
    d1 = defaultdict(int, Counter(L1)) 
    d2 = defaultdict(int, Counter(L2)) 

    o1, o2 = 0, 0 
    for k in d1: 
     o1 += min(d1[k], d2[k]) 
    for k in d2: 
     o2 += min(d1[k,0], d2[k]) 

    print((100*o1) if o1 else 0 "% of the first list overlaps with the second list") 
    print((100*o2) if o2 else 0 "% of the second list overlaps with the first list")