Комбинируйте списки с общими элементами

Скажем, у меня есть, например, следующий вложенный список:

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

Как я могу сгруппировать эти подсписки, получив объединение подсписок, которые имеют общий элемент, по крайней мере, с другим подсписком в группе? Итак, для предыдущего примера результат должен быть:

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

Таким образом, первые два подсписка объединяются, поскольку они совместно используют 'John'. Не мог бы кто-нибудь поделиться своими ценными мыслями?

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
11
0
1 844
5

Ответы 5

Во многих случаях моделирование проблемы в виде графа может значительно упростить довольно сложные задачи. В этом случае с точки зрения теории графов мы будем искать связанные компоненты графа.

Таким образом, простой способ сделать это - создать граф с помощью 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)


О компонентах связности (теория графов)

Более подробное объяснение по связанные компоненты:

In graph theory, a connected component (or just component) of an undirected graph is a subgraph in which any two vertices are connected to each other by paths, and which is connected to no additional vertices in the supergraph

По сути, этот код создает граф с ребрами из списка, где каждое ребро состоит из двух значений u,v, где u и v будут узлами, соединенными этим ребром.

И, следовательно, объединение подсписок по крайней мере с одним подсписком с общим элементом может быть преобразовано в проблему теории графов, поскольку все узлы достижимы между собой по существующим путям.

Интересный подход, объясните, пожалуйста, что это делает

Jab 21.12.2018 15:10

Что произойдет, если в подсписке более двух элементов?

Dani Mesejo 21.12.2018 15:21

@Aiyaz обновлен более общим случаем наличия подсписок с более чем 2 элементами

yatu 22.12.2018 10:31

Если порядок является важен, а список велик, вы можете использовать этот двухэтапный метод:

 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 ]

Для большей эффективности создайте set на l1;

Простой подход

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) 

Видеть

Составить список

Добавить против расширения

Вы можете использовать функцию 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'}]

Другие вопросы по теме