Python: симметричная разница между списком наборов строк
У меня есть список, который содержит несколько наборов строк, и я хотел бы найти симметричное различие между каждой строкой и другими строками в наборе.
Например, у меня есть следующий список:
targets = [{'B', 'C', 'A'}, {'E', 'C', 'D'}, {'F', 'E', 'D'}]
Для вышесказанного, желаемый результат:
[2, 0, 1]
поскольку в первом наборе A и B не найдены ни в одном из других наборов, для второго набора в этом наборе нет уникальных элементов, а для третьего набора F не найден ни в одном из других наборов.
Я думал о приближении к этому; найти пересечение каждого набора и вычесть длину пересечения из длины списка, но set.intersection(*), по-видимому, не работает со строками, поэтому я застрял:
set1 = {'A', 'B', 'C'}
set2 = {'C', 'D', 'E'}
set3 = {'D', 'E', 'F'}
targets = [set1, set2, set3]
>>> set.intersection(*targets)
set()
3 ответа
Ваш пример кода не работает, потому что он находит пересечение между всеми наборами, которое равно 0 (поскольку нигде не встречается элемент). Вы хотите найти разницу между каждым набором и объединением всех других наборов. Например:
set1 = {'A', 'B', 'C'}
set2 = {'C', 'D', 'E'}
set3 = {'D', 'E', 'F'}
targets = [set1, set2, set3]
result = []
for set_element in targets:
result.append(len(set_element.difference(set.union(*[x for x in targets if x != set_element]))))
print(result)
(обратите внимание, что [x for x in targets if x != set_element]
это просто набор всех остальных наборов)
Проблема, с которой вы столкнулись, заключается в том, что для всех трех наборов нет общих строк, поэтому ваш intersection
приходит пустой Это не вопрос строки, он будет работать так же с числами или чем-то еще, что вы можете поместить в набор.
Единственный способ выполнить глобальный расчет для всех наборов, а затем использовать его для определения количества уникальных значений в каждом, - это сначала подсчитать все значения (используя collections.Counter
), затем для каждого набора подсчитайте количество значений, которые обнаружились только один раз в общем количестве.
from collections import Counter
def unique_count(sets):
count = Counter()
for s in sets:
count.update(s)
return [sum(count[x] == 1 for x in s) for s in sets]
Попробуйте что-то вроде ниже:
Получите симметричную разницу с каждым набором. Затем пересекаются с заданным входным набором.
def symVal(index,targets):
bseSet = targets[index]
symSet = bseSet
for j in range(len(targets)):
if index != j:
symSet = symSet ^ targets[j]
print(len(symSet & bseSet))
for i in range(len(targets)):
symVal(i,targets)