2010-06-01 9 views
6

ce qui est la meilleure façon de prendre l'intersection de N-de listes en python?prenant intersection de N-de listes en python

si j'ai deux listes a et b, je sais que je peux faire:

a = set(a) 
b = set(b) 
intersect = a.intersection(b) 

mais je veux faire quelque chose comme un & b & c & d & ... pour un ensemble de listes arbitraires (idéalement sans conversion à un ensemble d'abord, mais si c'est le plus facile/moyen le plus efficace, je peux faire face à cela.)

Ie Je veux écrire une fonction intersect (* args) qui le fera arbitrairement pour de nombreux ensembles efficacement. Quelle est la meilleure façon de faire cela?

EDIT: Ma solution est de réduire (set.intersection, [a, b, c]) - est-ce bien?

merci.

+0

Sur 'réduire()', ce n'est pas exactement la meilleure idée, car il est en train de disparaître en Python 3. Il est aussi plus lent, de ce que je l'ai entendu, par rapport à une boucle. –

+0

double: http://stackoverflow.com/questions/2893500/take-the-intersection-of-an-arbitrary-number-of-lists-in-python –

+0

@Xavier: 'de functools importer reduce'. Il est supprimé des 'builtins', il n'est pas complètement éliminé. En outre, ce que vous avez entendu parler de sa vitesse est très imprécise: il peut être beaucoup plus rapide ou plus lent que pour une boucle. – tzot

Répondre

13

Cela fonctionne pour 1 ou plusieurs listes. Le cas 0 liste n'est pas si facile, car il devrait renvoyer un ensemble contenant toutes les valeurs possibles.

def intersection(first, *others): 
    return set(first).intersection(*others) 
+0

Magnifique. Vraiment simple. –

+0

Et donc la beauté de l'utilisation de built-ins. – jathanism

2

Cela fonctionne avec 1 ou plusieurs listes et ne pas utiliser plusieurs paramètres:

>>> def intersection(*listas): 
...  return set(listas[0]).intersection(*listas[1:]) 
...  
>>> intersection([1,2,3,4],[4,5,6],[2,4,5],[1,4,8]) 
set([4]) 
>>> intersection([1,2,3,4]) 
set([1, 2, 3, 4]) 
>>> 

Je ne sais pas ce qui est mieux que les autres réponses, de toute façon.

2
lists = [[5,4,3], [4,2], [6,2,3,4]] 

try: 
    # the following line makes one intersection too much, but I don't think 
    # this hurts performance noticably. 
    intersected = set(lists[0]).intersection(*lists) 
except ValueError: 
    # no lists[0] 
    intersected = set() 

print intersected   # set([4]) 

Les ensembles peuvent être croisés avec n'importe quel itérable, il n'est pas nécessaire de les convertir en un ensemble.