[英]Find sets of disjoint sets from a list of tuples or sets in python
here is the problem: I have a list of tuples (could be sets as well if needed).问题是:我有一个元组列表(如果需要,也可以设置)。 For instance:
例如:
a = [(1, 5), (4, 2), (4, 3), (5, 4), (6, 3), (7, 6)]
What I want to find is a list我想找到的是一个列表
r = [(1, 5, 4, 2, 3, 6, 7)]
because the intersection is not empty once all the sets are put together.因为一旦所有集合放在一起,交集就不是空的。
For the example例如
a = [(1, 5), (4, 2), (4, 3), (5, 4), (6, 3), (7, 6), (8, 9)]
the result should be结果应该是
r = [(1, 5, 4, 2, 3, 6, 7), (8, 9)]
Hope the problem is clear.希望问题很清楚。 So what is the most elegant way to do this in python, if any?
那么在python中最优雅的方法是什么,如果有的话?
Cheers干杯
These are the connected components of a graph, and can be found using a graphing library such as networkx
.这些是图形的连接组件,可以使用图形库(例如
networkx
。 For your second example:对于您的第二个示例:
>>> edges = [(1, 5), (4, 2), (4, 3), (5, 4), (6, 3), (7, 6), (8, 9)]
>>> graph = nx.Graph(edges)
>>> [tuple(c) for c in nx.connected_components(graph)]
[(1, 2, 3, 4, 5, 6, 7), (8, 9)]
Take a look at this implementation, it's fast because it's using Disjoint set with path compression, both find and merge operations are log(n):看看这个实现,它很快,因为它使用带有路径压缩的不相交集,查找和合并操作都是 log(n):
class DisjointSet(object):
def __init__(self,size=None):
if size is None:
self.leader = {} # maps a member to the group's leader
self.group = {} # maps a group leader to the group (which is a set)
self.oldgroup = {}
self.oldleader = {}
else:
self.group = { i:set([i]) for i in range(0,size) }
self.leader = { i:i for i in range(0,size) }
self.oldgroup = { i:set([i]) for i in range(0,size) }
self.oldleader = { i:i for i in range(0,size) }
def add(self, a, b):
self.oldgroup = self.group.copy()
self.oldleader = self.leader.copy()
leadera = self.leader.get(a)
leaderb = self.leader.get(b)
if leadera is not None:
if leaderb is not None:
if leadera == leaderb:
return # nothing to do
groupa = self.group[leadera]
groupb = self.group[leaderb]
if len(groupa) < len(groupb):
a, leadera, groupa, b, leaderb, groupb = b, leaderb, groupb, a, leadera, groupa
groupa |= groupb
del self.group[leaderb]
for k in groupb:
self.leader[k] = leadera
else:
self.group[leadera].add(b)
self.leader[b] = leadera
else:
if leaderb is not None:
self.group[leaderb].add(a)
self.leader[a] = leaderb
else:
self.leader[a] = self.leader[b] = a
self.group[a] = set([a, b])
def connected(self, a, b):
leadera = self.leader.get(a)
leaderb = self.leader.get(b)
if leadera is not None:
if leaderb is not None:
return leadera == leaderb
else:
return False
else:
return False
def undo(self):
self.group = self.oldgroup.copy()
self.leader = self.oldleader.copy()
def test():
x = DisjointSet()
x.add(0,1)
x.add(0,2)
x.add(3,4)
x.undo()
print x.leader
print x.group
if __name__ == "__main__":
test()
You can also undo the last add.您还可以撤消最后一次添加。 In your case you can do the following:
在您的情况下,您可以执行以下操作:
import DisjointSet
a = [(1, 5), (4, 2), (4, 3), (5, 4), (6, 3), (7, 6)]
d = DisjointSet()
for e in a:
d.add(*e)
print d.group
print d.leader
def pairs_to_whole(touching_pairs:list):
out = []
while len(touching_pairs)>0:
first, *rest = touching_pairs
first = set(first)
lf = -1
while len(first)>lf:
lf = len(first)
rest2 = []
for r in rest:
if len(first.intersection(set(r)))>0:
first |= set(r)
else:
rest2.append(r)
rest = rest2
out.append(first)
touching_pairs = rest
return out
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.