Если ваши наборы хранятся в s, например:
s = [set([1, 2]), set([1, 3]), set([1, 2, 3]), set([2, 4])]
Затем вы можете использовать itertools.combination , чтобы взять их два на два и рассчитать пересечение (обратите внимание, что, как указал Алекс, combinations
доступно только с версии 2.6). Вот с пониманием списка (только для примера):
from itertools import combinations
[ i[0] & i[1] for i in combinations(s,2) ]
Или, в цикле, что, вероятно, то, что вам нужно:
for i in combinations(s, 2):
inter = i[0] & i[1]
# processes the intersection set result "inter"
Итак, чтобы иметь длину каждого из них, эта «обработка» будет:
l = len(inter)
Это было бы весьма эффективно, поскольку он использует итераторы для вычисления каждой комбинации и не готовит их все заранее.
Редактировать : обратите внимание, что с этим методом каждый набор в списке "s" может фактически быть чем-то еще, что возвращает набор , как генератор. Сам список может быть просто генератором, если у вас мало памяти. Хотя это может быть намного медленнее, в зависимости от того, как вы генерируете эти элементы, но вам не нужно иметь весь список наборов в памяти одновременно (не то, чтобы это было проблемой в вашем случае).
Например, если каждый набор сделан из функции gen
:
def gen(parameter):
while more_sets():
# ... some code to generate the next set 'x'
yield x
with open("results", "wt") as f_results:
for i in combinations(gen("data"), 2):
inter = i[0] & i[1]
f_results.write("%d\n" % len(inter))
Редактировать 2 : Как собирать индексы (после комментария редрата).
Помимо быстрого решения, на которое я ответил в комментарии, более эффективным способом сбора заданных индексов было бы использование списка (index, set)
вместо списка set
.
Пример с новым форматом:
s = [(0, set([1, 2])), (1, set([1, 3])), (2, set([1, 2, 3]))]
Если вы строите этот список для расчета комбинаций в любом случае, вам будет просто адаптироваться к вашим новым требованиям. Основной цикл становится:
with open("results", "wt") as f_results:
for i in combinations(s, 2):
inter = i[0][1] & i[1][1]
f_results.write("length of %d & %d: %d\n" % (i[0][0],i[1][0],len(inter))
В цикле i[0]
и i[1]
будут кортежем (index, set)
, поэтому i[0][1]
- первый набор, i[0][0]
- его индекс.