如何将基于公共值的元组列表组合到列表中

时间:2016-03-24 21:18:30

标签: python list tuples

我有一长串的元组列表,例如:

[('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'],因为它们是通过元组。

我试图通过字典提出一些令人痛苦的失败。我确信有一些"更容易"溶液

谢谢你 马丁

2 个答案:

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