2010-01-08 8 views
2

j'ai deux listes imbriquées, chaque liste imbriquée contenant deux chaînes .: par exempleComparaison des listes imbriquées Python

list 1 [('EFG', '[3,4,5]'), ('DEF', '[2,3,4]')] and list 2 [('DEF', '[2,3,4]'), ('FGH', '[4,5,6]')] 

Je voudrais comparer les deux listes et récupérer ces listes imbriquées qui sont identiques les uns aux autres. Dans ce cas, seulement ('DEF','[2,3,4]') sera retourné. Les listes pourraient devenir longues. Y a-t-il un moyen efficace de le faire?

Répondre

8

Si les listes ne contiennent que tuples de chaîne, alors la meilleure façon de le faire est d'utiliser l'intersection des ensembles (&):

>>> set([('EFG', '[3,4,5]'), ('DEF', '[2,3,4]')]) & set([('DEF', '[2,3,4]'), ('FGH', '[4,5,6]')]) 
set([('DEF', '[2,3,4]')]) 
0

est ici une approche. Convertissez vos listes en ensembles et trouvez leurs intersections.

>>> a,b = set([('EFG', '[3,4,5]'), ('DEF', '[2,3,4]')]), set([('DEF', '[2,3,4]'), ('FGH', '[4,5,6]')]) 
>>> print a.intersection(b) 
set([('DEF', '[2,3,4]')]) 

Je ne pense pas que cela dégradera beaucoup avec la longueur de vos listes.

0

Il suffit d'utiliser mis le support intégré pour les jeux

def get_set(list1,list2): 
    s = set(list1) 
    s &= set(list2) 
    return s 

Et Boom il y a votre syndicat

+1

? Tu ne veux pas dire * intersection *? –

0
intersection = [item for item in list1 if item in list2] 

Mais seulement l'utiliser, si pour une raison quelconque, vous avez mutables dans vos listes et ne peut pas convertir en un ensemble. Bien sûr, tout dépend de la taille de vos listes et du nombre de doublons, mais cela pourrait bien être un facteur 10 plus lent.

+1

Cela va généralement être plus cher que les solutions basées sur des ensembles. – Brian

+0

Oui. Je le vois moi-même maintenant. C'est un facteur de 10 dans mes tests. – Debilski

+0

Toutefois, cela fonctionnera si les types contenus dans la liste ne sont pas modifiables, alors que toutes les solutions basées sur les ensembles échoueront. –

3

L'utilisation des ensembles pour le faire est une très bonne mise en œuvre, mais pour des performances optimales, vous devez utiliser uniquement un jeu:

set1 = set([('EFG', '[3,4,5]'), ('DEF', '[2,3,4]')]) 
matches = [x for x in [('DEF', '[2,3,4]'), ('FGH', '[4,5,6]')] if x in set1] 
+0

Pourriez-vous expliquer pourquoi c'est mieux? –

+0

La génération d'un ensemble à partir d'une séquence nécessite une itération, donc la génération des deux ensembles nécessite une itération à travers les deux séquences. De plus, l'exécution d'une intersection entre deux ensembles nécessite l'itération de l'un d'entre eux et l'exécution d'une opération d'appartenance de l'autre. Par conséquent, en les transformant tous les deux en séquences et en intersection, il faut répéter une séquence une fois, et l'autre deux fois. La solution que j'ai fournie ne convertit qu'une seule des listes, puis itère directement sur l'autre, en économisant un total d'itérations. –

+1

Si la liste -> définir les conversions et définir l'intersection se produit en C++ plutôt qu'en python, cela peut être plus rapide. – tgray

0
 python 3.2 
    [i for i in list1 for v in list2 if i==v] 
union
Questions connexes