簡體   English   中英

將列表與常見元素結合起來

[英]Combine lists with common elements

假設我有例如以下嵌套列表:

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

如何通過獲取與組內至少另一個子列表具有共同元素的子列表的聯合來對這些子列表進行分組? 所以對於前面的例子,結果應該是:

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

因此,前兩個子列表在共享'John'時被加入。 有人可以分享他們寶貴的想法嗎?

在許多情況下,將問題建模為圖形可以使相當復雜的任務變得更加容易。 在這種情況下,從圖論的角度來看,我們要尋找的是圖的連通分量

因此,解決此問題的一種簡單方法是使用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 ,您可以使用nx.add_path將它們添加為路徑而不是節點,因為它們可以連接多個節點:

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

G=nx.Graph()
for l in L:
    nx.add_path(G, l)
list(nx.connected_components(G))

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

我們還可以使用nx.draw可視化這些連接的組件:

pos = nx.spring_layout(G, scale=20, k=2/np.sqrt(G.order()))
nx.draw(G, pos, node_color='lightgreen', node_size=1000, with_labels=True)

在此處輸入圖像描述


關於連通分量(圖論)

有關連接組件的更詳細說明:

在圖論中,無向圖的連通分量(或只是分量)是一個子圖,其中任意兩個頂點通過路徑相互連接,並且不與超圖中的其他頂點相連

所以本質上,這段代碼創建了一個圖表,其中包含列表中的邊,其中每條邊由兩個值u,v組成,其中uv將是由該邊連接的節點。

因此,具有至少一個具有公共元素的子列表的子列表的並集可以轉換為圖論問題,因為所有節點都可以通過現有路徑在彼此之間到達。

一個簡單的方法

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) 

列出理解

追加與擴展

您可以在networkx中使用函數connected_components

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'}]

如果順序重要並且列表很大,您可以使用這兩種方法:

 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 個列表:

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

為了提高效率,請在l1上創建一個set

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM