在Python中成对设置交集

时间:2014-12-09 00:13:59

标签: python set set-intersection

如果我有一个可变数量的集合(让他们调用数字 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 的扩展程度如何增加,并且集合的大小变得过大。

一些其他背景信息:

  1. 每个集合的长度大致相同,但也非常大(足够大,将它们全部存储在内存中是一个现实问题,并且一个避免这种情况的算法虽然不是必需的)
  2. 任何两个集合之间的交叉点的大小与集合本身的大小相比非常小
  3. 如果有帮助,我们可以假设我们需要关于输入集的排序。

3 个答案:

答案 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