如果你的集合存储在s中,例如:
s = [set([1, 2]), set([1, 3]), set([1, 2, 3]), set([2, 4])]
然后您可以使用itertools.combinations 将它们两两取并计算交集(请注意,正如 Alex 所指出的,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:如何收集索引(根据 redrat 的评论)。
除了我在评论中回答的快速解决方案之外,收集设置索引的更有效方法是使用 (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] 是它的索引。