我有一长串的元组列表,例如:
[('5','9'), ('10','11'), ('1','2'), ('1','3'), ('1','4'), ('2','7'), ('3','8'), ('2','1'), ('3','1'), ('3','4'), ('5','6'), ('5','10'), ('10','12'), ('11','13'), ('13','14')]
如果他们共享任何共同点,我需要将它们组合成列表。所以示例中的输出将是:
['11', '10', '13', '12', '14', '5', '6', '9']
['1', '3', '2', '4', '7', '8']
澄清:输入是元组列表。我需要将所有元组和共享元素组合到一个列表中。所以,如果我有:[(' 1',' 2'),(' 1',' 3'),(&# 39; 1',' 4'),(' 4'' 5')],所有元素都应该放在一个列表中[& #39; 1',' 2',' 3',' 4',' 5'],因为它们是通过元组。
我试图通过字典提出一些令人痛苦的失败。我确信有一些"更容易"溶液
谢谢你 马丁答案 0 :(得分:0)
看起来你正在进行联合查找操作。 https://en.wikipedia.org/wiki/Disjoint-set_data_structure
从创建单件不相交集开始,每个集都有一个出现在列表中的数字。接下来,对于每个元组,将与元组中的数字对应的集合联合起来。
上述解决方案的元组数量的运行时间几乎是线性的。有关可能的union-find实现,请参阅A set union find algorithm。
答案 1 :(得分:0)
我们可以将此问题定位为在无向图中查找连接组件的问题。列表中出现的所有不同数字都可以视为图形的节点(顶点),并将对视为边缘。
这是一个带内联注释的简单算法:
l = [('5','9'), ('10','11'), ('1','2'), ('1','3'), ('1','4'), ('2','7'), ('3','8'), ('2','1'), ('3','1'), ('3','4'), ('5','6'), ('5','10'), ('10','12'), ('11','13'), ('13','14')]
# get all unique elements ("nodes") of `l'
nodes = set().union(*map(set, l))
# start with each node in its own connected component
comp = {node:{node} for node in nodes}
# now repeatedly merge pairs of components connected by edges in `l'
while True:
merged = False
new_l = [] # will drop edges that have already been used in a merge
for n1, n2 in l:
if comp[n1] is not comp[n2]:
# the two connected components are not the same, so merge them
new_comp = comp[n1] | comp[n2]
for n in new_comp:
comp[n] = new_comp
merged = True
else:
# keep the pair for the next iteration
new_l.append((n1, n2))
if not merged:
# all done
break
l = new_l
# now print all distinct connected components
for c in set(map(frozenset, comp.values())):
print list(c)
打印出来:
['1', '3', '2', '4', '7', '8']
['11', '10', '13', '12', '14', '5', '6', '9']