2010-03-29 8 views

Respuesta

278

De Python versión 2.6 en adelante usted puede utilizar varios 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 list expansion

+0

¿Puede explicarme o señalarme la documentación relevante para lo que significa '* setlist' aquí? (Específicamente, ¿qué hace el asterisco?) ¡Gracias! – PurpleVermont

+6

Para cualquier otra persona que pueda tener la misma pregunta que yo, encontré la respuesta aquí: http://stackoverflow.com/questions/400739/what-does-asterisk-mean-in-python – PurpleVermont

10

Si usted no tiene Python 2.6 o superior, la alternativa es escribir un bucle explícito para:

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 puede utilizar 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, muchos programadores de Python no me gusta, including Guido himself:

Hace alrededor de 12 años, Python adquirió lambda, reduce(), fil ter() y map(), cortesía de (creo) un hacker Lisp que los echó de menos y envió parches de trabajo. Pero, a pesar del valor PR, creo que estas características deberían cortarse de Python 3000.

Así que 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.

+8

Tenga en cuenta que Guido dice que el uso de 'reduce' es "limitada a los operadores asociativos", lo cual es aplicable en este caso. 'reducir 'es a menudo difícil de entender, pero para' & 'no es tan malo. –

+0

['set_list y reduce (set.intersection, set_list)'] (http://stackoverflow.com/a/1404146/4279) – jfs

+0

Consulte https://www.python.org/doc/essays/list2str/ para optimizaciones útiles que implican reducir. En general, se puede usar bastante bien para compilar listas, conjuntos, cadenas, etc. También vale la pena mirar https://github.com/EntilZha/PyFunctional – Andreas

41

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]) 
1

Aquí estoy ofreciendo una función genérica para la intersección de conjuntos múltiples 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:]) 

Guido podría no les gusta reduce, pero estoy un poco aficionado a ella :)

+0

Debe verificar la longitud de ' sets' en lugar de intentar acceder a 'sets [0]' y capturar 'IndexError'. – bfontaine

+0

Esto no es un cheque simple; 'a_set' se usa en la devolución final. – tzot

+0

¿No puedes hacer 'return reduce (sets [0], sets [1:]) if sets else set()'? – bfontaine

11

Claramente set.intersection es lo que quiere aquí, pero en caso de que alguna vez necesite una generalización de "tomar la suma de todos estos", "tomar el producto de todos estos", "tomar el xor de todos estos", lo que estás buscando es el reduce f unción:

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} 
Cuestiones relacionadas