subconjunto programacion potencia lista interseccion entre diferencia convertir conjuntos conjunto cardinalidad python set set-intersection

programacion - subconjunto python



La mejor forma de encontrar la intersección de varios conjuntos? (5)

A partir de 2.6, set.intersection toma arbitrariamente muchos iterables.

>>> s1 = set([1, 2, 3]) >>> s2 = set([2, 3, 4]) >>> s3 = set([2, 4, 6]) >>> s1 & s2 & s3 set([2]) >>> s1.intersection(s2, s3) set([2]) >>> sets = [s1, s2, s3] >>> set.intersection(*sets) set([2])

Tengo una lista de conjuntos:

setlist = [s1,s2,s3...]

Quiero s1 ∩ s2 ∩ s3 ...

Puedo escribir una función para hacerlo al realizar una serie de s1.intersection(s2) parejas, etc.

¿Hay una manera recomendada, mejor o integrada?


Aquí estoy ofreciendo una función genérica para la intersección de múltiples conjuntos tratando de aprovechar el mejor método disponible:

def multiple_set_intersection(*sets): """Return multiple set intersection.""" try: return set.intersection(*sets) except TypeError: # this is Python < 2.6 or no arguments pass try: a_set= sets[0] except IndexError: # no arguments return set() # return empty set return reduce(a_set.intersection, sets[1:])

Puede que a Guido no le guste reduce , pero me gusta mucho :)


Desde la versión 2.6 de Python puede usar múltiples argumentos para set.intersection() , como

u = set.intersection(s1, s2, s3)

Si los conjuntos están en una lista, esto se traduce en:

u = set.intersection(*setlist)

donde *a_list es una lista de expansión


La set.intersection claramente set.intersection es lo que desea aquí, pero en caso de que necesite una generalización de "tome la suma de todos estos", "tome el producto de todos estos", "tome el xor de todos estos", lo que está buscando para es la función de reduce :

from operator import and_ from functools import reduce print(reduce(and_, [{1,2,3},{2,3,4},{3,4,5}])) # = {3}

o

print(reduce((lambda x,y: x&y), [{1,2,3},{2,3,4},{3,4,5}])) # = {3}


Si no tiene Python 2.6 o superior, la alternativa es escribir un ciclo for explícito:

def set_list_intersection(set_list): if not set_list: return set() result = set_list[0] for s in set_list[1:]: result &= s return result set_list = [set([1, 2]), set([1, 3]), set([1, 4])] print set_list_intersection(set_list) # Output: set([1])

También puedes usar reduce :

set_list = [set([1, 2]), set([1, 3]), set([1, 4])] print reduce(lambda s1, s2: s1 & s2, set_list) # Output: set([1])

Sin embargo, a muchos programadores de Python no les gusta, incluido el propio Guido :

Hace aproximadamente 12 años, Python adquirió lambda, reduce (), filter () y map (), cortesía de (creo) un pirata informático Lisp que los echó de menos y envió parches de trabajo. Pero, a pesar del valor de las relaciones públicas, creo que estas características deberían cortarse de Python 3000.

Entonces ahora reduce (). Esto es realmente el que siempre he odiado, porque, aparte de algunos ejemplos que involucran + o *, casi cada vez que veo una llamada de reducción () con un argumento de función no trivial, necesito agarrar lápiz y papel para Diagrama lo que se está alimentando en esa función antes de entender qué se supone que debe hacer el reducir (). Así que, en mi opinión, la aplicabilidad de reduce () se limita bastante a los operadores asociativos, y en todos los demás casos es mejor escribir explícitamente el ciclo de acumulación.