如果我有一个可变数量的集合(让他们调用数字 n ),每个集合最多只有 m 元素,那么该怎么办?计算所有对的成对交叉点的最有效方法是什么?请注意,这与所有 n 集的交集不同。
例如,如果我有以下几组:
A={"a","b","c"}
B={"c","d","e"}
C={"a","c","e"}
我希望能够找到:
intersect_AB={"c"}
intersect_BC={"c", "e"}
intersect_AC={"a", "c"}
另一种可接受的格式(如果它使事情变得更容易)将是给定集合中包含相同项目的集合的项目映射。例如:
intersections_C={"a": {"A", "C"},
"c": {"A", "B", "C"}
"e": {"B", "C"}}
我知道这样做的一种方法是创建一个字典,将所有 n 集的并集中的每个值映射到它出现的集合列表,然后迭代遍历所有用于创建上述intersections_C
等列表的值,但我不确定 n 的扩展程度如何增加,并且集合的大小变得过大。
一些其他背景信息:
答案 0 :(得分:5)
这应该做你想做的事情
import random as RND
import string
import itertools as IT
模拟一些数据
fnx = lambda: set(RND.sample(string.ascii_uppercase, 7))
S = [fnx() for c in range(5)]
生成S中集合的索引列表,以便可以在下面更简洁地引用集合
idx = range(len(S))
获取S中所有可能唯一的项目对;但是,由于集合交叉是可交换的,我们需要组合而不是排列
pairs = IT.combinations(idx, 2)
编写一个函数执行集合交集
nt = lambda a, b: S[a].intersection(S[b])
将此功能折叠成对&键入每个函数调用其参数的结果
res = dict([ (t, nt(*t)) for t in pairs ])
下面的结果,根据OP中列出的第一个选项格式化,是一个字典,其中值是两个序列的集合交集;每个值键入到由这些序列的两个索引组成的元组
这个解决方案,实际上只是两个代码行:(i)计算排列; (ii)然后在每个排列上应用一些函数,将返回的值存储在结构化容器(键值)容器中
此解决方案的内存占用量很小,但您可以通过在最后一步返回生成器表达式来做得更好,即
res = ( (t, nt(*t)) for t in pairs )
注意到使用这种方法,在内存中没有写出对的序列和相应的交叉点 - 即,对和 res 都是迭代器。
答案 1 :(得分:3)
如果我们可以假设输入集是有序的,那么伪合并方法看起来很有希望。将每个集合视为已排序的流,并行地推进流,始终只推进所有当前迭代器中值最低的那些流。每次迭代器前进时,将每个当前值与新的最小值进行比较,并将匹配项转储到同一项集合中。
答案 2 :(得分:-2)
如何使用set的交集方法。见下文:
A={"a","b","c"}
B={"c","d","e"}
C={"a","c","e"}
intersect_AB = A.intersection(B)
intersect_BC = B.intersection(C)
intersect_AC = A.intersection(C)
print intersect_AB, intersect_BC, intersect_AC