具有共同元素的子列表的并集

时间:2018-12-21 14:05:32

标签: python list networkx

例如,我有以下嵌套列表:

L = [['John','Sayyed'], ['John' , 'Simon'] ,['bush','trump'],
     ['Sam','Suri','NewYork'],['Suri','Orlando','Canada']]

如何通过将具有共同元素的子列表与至少一个子列表组合在一起来对这些子列表进行分组?因此,对于前面的示例,结果应为:

[['John','Sayyed','Simon'] ,['bush','trump'],
 ['Sam','Suri','NewYork','Orlando','Canada']]

因此,前两个子列表在共享'John'时会合并在一起。 有人可以分享他们的宝贵思想吗?

5 个答案:

答案 0 :(得分:10)

您可以使用networkx。生成图形,并使用add_edges_from将列表添加为图形边缘。然后使用connected_components,它将为您提供图形中一组已连接组件的列表:

import networkx as nx 

L = [['John','Sayyed'], ['John' , 'Simon'] ,['bush','trump']

G=nx.Graph()
G.add_edges_from(L)
list(nx.connected_components(G))

[{'John', 'Sayyed', 'Simon'}, {'bush', 'trump'}]

更新

如果子列表包含的元素超过2个,则可以从每个子列表中获取所有长度2 combinations并将其用作网络边缘:

from itertools import combinations, chain

L = [['John','Sayyed'], [ 'John' , 'Simon'] ,['bush','trump'],
     ['Sam','Suri','NewYork'],['Suri','Orlando','Canada']]

L2_nested = [list(combinations(l,2)) for l in L]
L2 = list(chain.from_iterable(L2_nested))
#[('John', 'Sayyed'), ('John', 'Simon'), ('bush', 'trump'), ('Sam', 'Suri')...

G=nx.Graph()
G.add_edges_from(L2)
list(nx.connected_components(G))

[{'John', 'Sayyed', 'Simon'},
{'bush', 'trump'},
{'Canada', 'NewYork', 'Orlando', 'Sam', 'Suri'}]

Networkx还允许您使用nx.draw可视化网络:

pos = nx.spring_layout(G, scale=20)
nx.draw(G, pos, node_color='lightblue', node_size=500, with_labels=True)

enter image description here


详细信息

关于connected components的更详细说明:

  

在图论中,无向图的连接部分(或仅一个部分)是一个子图,其中任意两个顶点通过路径相互连接,并且不与上图中的其他顶点连接。

因此,从本质上讲,这段代码创建了一个具有列表边缘的图形,其中每个边缘由两个值u,v组成,其中uv是由该边缘连接的节点。

因此,子列表与至少一个具有公共元素的子列表的并集可以转换为图论问题,因为所有节点之间都可以通过现有路径到达。

答案 1 :(得分:1)

如果订单重要并且列表很大,则可以使用以下两种方法:

 l = [['john', 'sayyid'], ['john', 'simon'], ['b', 't']]

 def join(l1, l2):
     mset = set(l1)
     result = l1[:] # deep copy
     for each in l2:
         if each in mset:
             continue
         else:
             result.append(each)
     return result

要在主列表中合并,只需按其等级调用列表并弹出原始列表:

l1 = l.pop(0)
l2 = l.pop(0)
l.insert(0, join(l1, l2))
>>> l:
[['john', 'sayyid', 'simon'], ['b', 't']]

答案 2 :(得分:0)

要合并2个列表:

merge = lambda l1, l2: l1 + [ x for x in l2 if x not in l1 ]

要提高效率,请在set上创建一个l1

答案 3 :(得分:0)

一种简单的方法

L = [['John','Sayyed'], [ 'John' , 'Simon'] ,['bush','trump']]
L[0].extend([x for x in L[1] if x not in L[0]])
L.pop(1)
print(L) 

请参见

List Comprehensions

Append vs Extend

答案 4 :(得分:0)

您可以在connected_components中使用函数networkx

import networkx as nx 
​
L = [['John','Sayyed'], ['John' , 'Simon'] ,['bush','trump'],
     ['Sam','Suri','NewYork'],['Suri','Orlando','Canada']]
​
G = nx.Graph()
​
for i in L:
    G.add_path(i)
​
lst = list(nx.connected_components(G))
print(lst)

输出:

[{'John', 'Sayyed', 'Simon'},
 {'bush', 'trump'},
 {'Canada', 'NewYork', 'Orlando', 'Sam', 'Suri'}]