Tome la intersección de un número arbitrario de listas en python

Supongamos que tengo una lista de listas de elementos que son todos iguales (usaré int s en este ejemplo)

 [range(100)[::4], range(100)[::3], range(100)[::2], range(100)[::1]] 

¿Cuál sería una manera agradable y / o eficiente de tomar la intersección de estas listas (de modo que obtendría todos los elementos que están en cada una de las listas)? Para el ejemplo que sería:

 [0, 12, 24, 36, 48, 60, 72, 84, 96] 

Utilice conjuntos, que tienen un método de intersección.

 >>> s = set() >>> s.add(4) >>> s.add(5) >>> s set([4, 5]) >>> t = set([2, 4, 9]) >>> s.intersection(t) set([4]) 

Para tu ejemplo, algo como

 >>> data = [range(100)[::4], range(100)[::3], range(100)[::2], range(100)[::1]] >>> sets = map(set, data) >>> print set.intersection(*sets) set([0, 96, 36, 72, 12, 48, 84, 24, 60]) 

Creo que el módulo integrado debería hacer el truco.

 >>> elements = [range(100)[::4], range(100)[::3], range(100)[::2], range(100)[::1]] >>> sets = map(set, elements) >>> result = list(reduce(lambda x, y: x & y, sets)) >>> print result [0, 96, 36, 72, 12, 48, 84, 24, 60] 

Conviértalos a conjuntos y use el método set.intersection , reduciendo la lista de conjuntos:

 xs = [range(100)[::4], range(100)[::3], range(100)[::2], range(100)[::1]] reduce(set.intersection, [set(x) for x in xs]) 

reduce es un dispositivo de progtwigción funcional que itera a través de cualquier iterable y aplica la función proporcionada a los primeros dos elementos, luego al resultado y al siguiente, y luego el resultado de eso y el siguiente, y así sucesivamente.

Voy a responder mi propia pregunta:

 lists = [range(100)[::4],range(100)[::3],range(100)[::2],range(100)[::1]] out = set(lists[0]) for l in lists[1:]: out = set(l).intersection(out) print out 

o

 print list(out) 
 l = [range(100)[::4], range(100)[::3], range(100)[::2], range(100)[::1]] l = [set(i) for i in l] intersect = l[0].intersection(l[1]) for i in l[2:]: intersect = intersect.intersection(i) 

Puedes tratarlos como conjuntos y usar set.intersection() :

 lists = [range(100)[::4], range(100)[::3], range(100)[::2], range(100)[::1]] sets = [set(l) for l in lists] isect = reduce(lambda x,y: x.intersection(y), sets) 

Aquí hay una sola línea que usa la vieja función incorporada all() :

 list(num for num in data[0] if all(num in range_ for range_ in data[1:])) 

Curiosamente, esto es (creo) más legible y más rápido que usar el set para set de datos más grandes.