Python: ¿Ves si un conjunto contiene otro por completo?


82

¿Existe una forma rápida de comprobar si un conjunto contiene por completo otro?

Algo como:

>>>[1, 2, 3].containsAll([2, 1])
True

>>>[1, 2, 3].containsAll([3, 5, 9])
False

Respuestas:


125

Esas son listas, pero si realmente te refieres a conjuntos, puedes usar el método issubset.

>>> s = set([1,2,3])
>>> t = set([1,2])
>>> t.issubset(s)
True
>>> s.issuperset(t)
True

Para obtener una lista, no podrá hacer nada mejor que marcar cada elemento.


3
Tengo una extraña sensación de dejavu cuando veo esta respuesta
Christophe Roussy

tienes que ser consciente de la semántica de issubset()no escontains()
wikier

37

Para completar: esto es equivalente a issubset(aunque posiblemente un poco menos explícito / legible):

>>> set([1,2,3]) >= set([2,1])
True
>>> set([1,2,3]) >= set([3,5,9])
False

El problema es que a = set ([]) y b = set (['a', 'b']) entonces a.issubset (b) es True
darkman

4

Una opción queda intacta: la resta:

>>> {1, 2} - {1, 2, 3}
set([])
>>> {1, 2, 3} - {1, 2}
set([3])

Básicamente, verifica qué elementos de la primera lista no están en la segunda.

Lo encontré muy útil ya que podía mostrar qué valores faltan:

>>> def check_contains(a, b):
...     diff = a - b
...     if not diff:
...         # All elements from a are present in b
...         return True
...     print('Some elements are missing: {}'.format(diff))
...     return False
...
>>> check_contains({1, 2}, {1, 2, 3})
True
>>> check_contains({1, 2, 3}, {1, 2})
Some elements are missing: set([3])
False

3

Puede utilizar set.issubset()o set.issuperset()(o sus contrapartes basadas en el operador: <=y >=). Tenga en cuenta que los métodos aceptarán cualquier iterable como argumento, no solo un conjunto:

>>> {1, 2}.issubset([1, 2, 3])
True
>>> {1, 2, 3}.issuperset([1, 2])
True

Sin embargo, si usa operadores, ambos argumentos deben establecerse:

>>> {1, 2} <= {1, 2, 3}
True
>>> {1, 2, 3} >= {1, 2}
True

3

Si sospecha que un conjunto es un subconjunto de otro e interseca esos dos conjuntos, el resultado es igual a sí mismo si es un subconjunto.

a = [2,1,3,3]
b = [5,4,3,2,1]
set(a).intersection(set(b)) == set(a)
>>True

1
Vamos A = set(a)y B = set(b)por la cordura. Entonces esta comparación es eficientemente reducible a len(A.intersection(B)) == len(A). Es decir, los conjuntos en sí mismos no necesitan compararse por elementos; sólo es necesario comparar la cardinalidad de estos conjuntos. Sin embargo, incluso esta optimización es probablemente insuficiente para hacer que este enfoque sea preferible. Los enfoques y dramáticamente más legibles y eficientes son casi con certeza lo que todos quieren. issubset()<=
Cecil Curry

@CecilCurry True: utilicé la palabra 'cardinalidad' incorrectamente ya que es una medida de longitud. Actualicé la redacción. Su optimización es un error basado en mi error. No es una optimización. La redacción literal de "intersección ()" se lee más explícitamente que las implicaciones sobrecargadas de "> =" y afirmar que "issubset ()" es más fácil de leer es una especie de eliminación de lo obvio, ya que es la respuesta más popular. Siéntase libre de aportar una solución creativa más allá de repetir las respuestas de otros.
Jordan Stefanelli

1
>>> set([1,2,3]).issuperset(set([2,1]))
True 
>>>    
>>> set([1,2,3]).issuperset(set([3,5,9]))
False

3
Considere formatear su respuesta correctamente y agregue alguna explicación.
Sam

0

Debajo de la función, devuelva 0 si la lista principal no contiene la sublista completamente y 1 si la contiene completamente.

def islistsubset(sublist,mainlist):
     for item in sublist:
             if item in mainlist:
                     contains = 1
             else:
                     contains = 0
                     break;
     return contains

1
Esto es O (n ^ 2) mientras que el uso de operaciones de conjunto, ya que en algunas de las respuestas existentes, es mucho más rápido. Esto también se puede escribir de forma sencilla any(item in mainlist for item in sublist).
Iguananaut

Estoy de acuerdo, de hecho, también podría escribir def islistsubset (sublist, mainlist): contains = 1 para el elemento en la sublista: si el elemento en la lista principal: continuar más: contiene = 0 descanso; return contiene Por lo tanto, solo 2 asignaciones por llamada
Bobin Motti Thomas

@BobinMottiThomas Puede devolver directamente Verdadero o Falso sin crear ninguna variable temporal. para el elemento en list_a: si el elemento no está en list_b: return False return True
Jordan Stefanelli
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.