web-dev-qa-db-fra.com

Union de sous-listes avec des éléments communs

Disons que j'ai par exemple la liste imbriquée suivante:

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

Comment puis-je regrouper ces sous-listes, en obtenant l'union de sous-listes qui ont un élément commun avec au moins une autre sous-liste au sein du groupe? Donc, pour l'exemple précédent, le résultat devrait être:

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

Ainsi, les deux premières sous-listes sont jointes alors qu'elles partagent 'John'. Quelqu'un pourrait-il s'il vous plaît partager ses précieuses pensées?

6
Aiyaz

Vous pouvez utiliser networkx pour cela. Générez un graphique et ajoutez votre liste sous forme d'arêtes à l'aide de add_edges_from . Ensuite, utilisez connected_components , qui vous donnera avec précision une liste d’ensembles des composants connectés dans le graphique:

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

Mettre à jour 

Dans le cas de sous-listes comportant plus de 2 éléments, vous pouvez obtenir toute la longueur 2combinations de chaque sous-liste et les utiliser comme extrémités du réseau:

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

Détails 

Explication plus détaillée sur composants connectés :

En théorie des graphes, un composant connecté (ou juste un composant) d'un graphe non dirigé est un sous-graphe dans lequel deux sommets quelconques sont connectés l'un à l'autre par des chemins et qui n'est connecté à aucun sommet supplémentaire dans le supergraph.

En gros, ce code crée un graphique, avec des arêtes de la liste, chaque bord étant composé de deux valeurs u,vu et v seront des nœuds connectés par ce bord. 

Et par conséquent, l'union des sous-listes avec au moins une sous-liste avec un élément commun peut être traduite en un problème de théorie des graphes comme tous les nœuds qui sont accessibles les uns aux autres par les chemins existants. Un exemple de ceci peut être vu dans le graphique suivant , qui a trois composantes connectées:


 enter image description here

9
yatu

Si ordre est important et que la liste est longue, vous pouvez utiliser cette méthode en deux temps:

 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

Pour fusionner dans la liste principale, vous pouvez simplement appeler la liste par son rang et afficher la liste d'origine:

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

Une approche simple 

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) 

Voir 

Liste des compréhensions

Append vs Extend

0
nandu kk

Pour fusionner 2 listes:

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

Pour être plus efficace, créez une set sur l1;

0
Cyker