关于将子列表与相同数字链接在一起的python

时间:2017-05-27 23:27:48

标签: python list

我需要将具有相同元素的子列表组合在一起 例如:

list1 =[[1, 0], [2, 1], [30, 32]]

会将[1, 0][2, 1]联系在一起,因为它们都包含1,而这两者会合并为[0, 1, 2]

所以在链接之后,新列表应该是:

new_list1 = [[1, 0, 2], [30, 32]]

IE:在子列表中不应该是相同的数字,顺序并不重要。

更长的例子:

list2 = [[2, 3], [4, 3], [6, 5], [7, 6], [7, 8], [13, 14], [30, 32]]
链接后

将是

new_list2 = [[2, 3, 4], [6, 5, 7, 8], [13, 14], [30, 32]]

那么如何以一般方式完成呢?

2 个答案:

答案 0 :(得分:2)

要以一般方式对子列表进行分组,您可以:

代码:

def linking_sublists(lists):
    index = {}
    sets = []
    for l in lists:
        found = None
        for i in l:
            if i in index:
                # this list has an element we have already seen
                if found:
                    # combine two sets
                    to_remove = index[i]
                    if found != to_remove:
                        for j in index[i]:
                            found.add(j)
                            index[j] = found
                        to_remove.clear()
                else:
                    found = index[i]

        if found is not None:
            s = found
            for i in l:
                s.add(i)
        else:
            s = set(l)
            sets.append(s)
        for i in l:
            index[i] = s

    return [list(sorted(s)) for s in sets if s]

如何:

此函数使用集合和索引dict将具有匹配元素的任何列表分组到集合中,并跟踪哪些元素已在set中。

测试代码:

list_2 = [[2, 3], [4, 3], [6, 5], [7, 6], [7, 8], [13, 14], [30, 32]]
print(linking_sublists(list_2))

list_3 = [[2, 3], [4, 3], [6, 5], [7, 6], [7, 8], [30, 32], [4, 5], [3, 4]]
print(linking_sublists(list_3))

结果:

[[2, 3, 4], [5, 6, 7, 8], [13, 14], [30, 32]]
[[2, 3, 4, 5, 6, 7, 8], [30, 32]]

答案 1 :(得分:1)

查看此问题的一种方法是将每个子列表视为图中的节点。如果两个节点具有共同项,则它们共享边缘。

然后可以使用图形的岛("connected components" or just "components")来构建新列表。 list2的图表如下所示:

[2,3]<--->[4,3]

[6,5]<--->[7,6]<--->[7,8]

[13,14]   [30,32]

代码草图(未经测试):

list2=[[2,3],[4,3],[6,5],[7,6],[7,8],[13,14],[30,32]]

# Convert to tuples for easier handling
l2 = [tuple(item) for item in list2]

# Build a graph
graph = {item: set() for item in l2}
for sublist in l2:
    for sublist2 in l2:
        if sublist == sublist2:
            continue
        for item in sublist:
            if item in sublist2:
                graph[sublist].add(sublist2)

# Find all nodes that start_node is connected to
def island(graph, start_node):
    visited = set()
    visited.add(start_node)
    frontier = set(graph[start_node])
    while frontier:
        node = frontier.pop()
        visited.add(node)
        frontier.update(n for n in graph[node] if n not in visited)
    return visited

# Find all islands
islands = []
for sublist in l2:
    i = island(graph, sublist)
    if i not in islands:
        islands.append(i)

# Build the new lists by getting all unique numbers from each island
[list(set(item for sublist in island for item in sublist)) for island in islands]

# Output:
# [[2, 3, 4], [8, 5, 6, 7], [13, 14], [32, 30]]

以上内容可以改进,无论是构建图表的方式还是找到组件的方式都可以提高效率。

这种思维可以用来解决许多不同的问题。也就是说,我更喜欢Stephen Rauch的解决方案,因为它简单。