¿Cómo comprobar si todos los elementos siguientes están en una lista?

114

Descubrí que hay una pregunta relacionada sobre cómo encontrar si existe al menos un elemento en una lista:
¿Cómo verificar si uno de los siguientes elementos está en una lista?

Pero, ¿cuál es la mejor forma pitónica de averiguar si todos los elementos existen en una lista?

Buscando en los documentos encontré esta solución:

>>> l = ['a', 'b', 'c']
>>> set(['a', 'b']) <= set(l)
True
>>> set(['a', 'x']) <= set(l)
False

Otra solución sería esta:

>>> l = ['a', 'b', 'c']
>>> all(x in l for x in ['a', 'b'])
True
>>> all(x in l for x in ['a', 'x'])
False

Pero aquí debes escribir más.

¿Hay otras soluciones?

sirex
fuente
5
¿Qué pasa con set(smaller) <= set(larger)?
eumiro
1
Creo que sus segundas soluciones con 'todos' me parecen bien y pitónicas.
Jiho Noh

Respuestas:

157

Los operadores como <=en Python generalmente no se anulan para significar algo significativamente diferente a "menor o igual a". Es inusual que la biblioteca estándar haga esto; me huele a API heredada.

Utilice el método equivalente y más nombrado claramente, set.issubset. Tenga en cuenta que no es necesario convertir el argumento en un conjunto; lo hará por usted si es necesario.

set(['a', 'b']).issubset(['a', 'b', 'c'])
Glenn Maynard
fuente
2
no sabía que podía pasar la lista directamente como un argumento a issubset ... ¡agradable!
tsimbalar
1
Si bien estoy de acuerdo con el sentimiento, estoy bastante bien con la idea <=y el issubsetsignificado de lo mismo. ¿Por qué no te gusta?
Kirk Strauser
2
@Just: principalmente, porque no es obvio lo que <=significa para un conjunto sin buscarlo en los documentos o tener un conocimiento previo de lo que significa en la teoría de conjuntos, mientras que todos saben lo que issubsetsignifica automáticamente.
Glenn Maynard
2
¿Conoce el operador matemático para el subconjunto (no apropiado)? Básicamente se parece mucho a un <=;) redondeado
dom0
amo esta solución. ¿Hay alguna manera de obtener una ubicación de índice o un valor de lista en lugar de un bool (Verdadero: Falso)?
Vlad Gulin
62

Probablemente lo usaría setde la siguiente manera:

set(l).issuperset(set(['a','b'])) 

O de otra forma :

set(['a','b']).issubset(set(l)) 

Lo encuentro un poco más legible, pero puede ser demasiado rápido. Los conjuntos son particularmente útiles para calcular la unión / intersección / diferencias entre colecciones, pero puede que no sea la mejor opción en esta situación ...

tsimbalar
fuente
De hecho, MySet.issubset(MyOtherSet)y MySet <= MyOtherSetson lo mismo.
Wok
1
@wok: oh, no lo sabía, pero creo que la sintaxis <= es un poco confusa, ya que se puede usar una sintaxis similar con listas, pero con un significado muy diferente.
tsimbalar
3
No es tan confuso si recuerda que la inclusión define un orden parcial en cualquier conjunto de conjuntos. En realidad, es un poco confuso que <=tenga el significado que tiene para las secuencias: uno podría esperar que signifique 'es una subsecuencia' en lugar de un orden lexicográfico.
aaronasterling
1
@aaronasterling: mmm, personalmente no pienso demasiado en "orden parcial" cuando escribo el código :-), pero estoy de acuerdo en el hecho de que usar <=con secuencias también se siente extraño, de alguna manera ...
tsimbalar
3
Me encontré con un pequeño problema que me gustaría mencionar: si usa este método, está convirtiendo sus listas en conjuntos, lo que significa que no hay duplicados. set(['a','a']).issubset(['a'])devuelve True.
Orangestar
11

Me gustan estos dos porque parecen los más lógicos, el último es más corto y probablemente el más rápido (se muestra aquí usando una setsintaxis literal que se ha actualizado a Python 2.7):

all(x in {'a', 'b', 'c'} for x in ['a', 'b'])
#   or
{'a', 'b'}.issubset({'a', 'b', 'c'})
martineau
fuente
La solución "all" es la más rápida cuando se mide con timeit (). Esta debería ser la respuesta aceptada.
Attersson
3

¿Qué pasa si sus listas contienen duplicados como este?

v1 = ['s', 'h', 'e', 'e', 'p']
v2 = ['s', 's', 'h']

Los conjuntos no contienen duplicados. Entonces, la siguiente línea devuelve True.

set(v2).issubset(v1)

Para contar los duplicados, puede usar el código:

v1 = sorted(v1)
v2 = sorted(v2)


def is_subseq(v2, v1):
    """Check whether v2 is a subsequence of v1."""
    it = iter(v1)
    return all(c in it for c in v2) 

Entonces, la siguiente línea devuelve False.

is_subseq(v2, v1)
Max
fuente
1

Esto era lo que estaba buscando en línea, pero desafortunadamente no lo encontré en línea, sino mientras experimentaba con el intérprete de Python.

>>> case  = "caseCamel"
>>> label = "Case Camel"
>>> list  = ["apple", "banana"]
>>>
>>> (case or label) in list
False
>>> list = ["apple", "caseCamel"]
>>> (case or label) in list
True
>>> (case and label) in list
False
>>> list = ["case", "caseCamel", "Case Camel"]
>>> (case and label) in list
True
>>>

y si tiene una lista muy larga de variables contenidas en un sublist variable

>>>
>>> list  = ["case", "caseCamel", "Case Camel"]
>>> label = "Case Camel"
>>> case  = "caseCamel"
>>>
>>> sublist = ["unique banana", "very unique banana"]
>>>
>>> # example for if any (at least one) item contained in superset (or statement)
...
>>> next((True for item in sublist if next((True for x in list if x == item), False)), False)
False
>>>
>>> sublist[0] = label
>>>
>>> next((True for item in sublist if next((True for x in list if x == item), False)), False)
True
>>>
>>> # example for whether a subset (all items) contained in superset (and statement)
...
>>> # a bit of demorgan's law
...
>>> next((False for item in sublist if item not in list), True)
False
>>>
>>> sublist[1] = case
>>>
>>> next((False for item in sublist if item not in list), True)
True
>>>
>>> next((True for item in sublist if next((True for x in list if x == item), False)), False)
True
>>>
>>>
Emirhan Özlen
fuente
0

Un ejemplo de cómo hacer esto usando una expresión lambda sería:

issublist = lambda x, y: 0 in [_ in x for _ in y]
Jundullah
fuente
1
Agregue comentarios para explicar / elaborar su respuesta
Sharad
0

No es el caso de OP, pero, para cualquiera que quiera afirmar la intersección en los dictados y terminó aquí debido a una mala búsqueda en Google (por ejemplo, yo), debe trabajar con dict.items:

>>> a = {'key': 'value'}
>>> b = {'key': 'value', 'extra_key': 'extra_value'}
>>> all(item in a.items() for item in b.items())
True
>>> all(item in b.items() for item in a.items())
False

Esto se debe a que dict.itemsdevuelve tuplas de pares clave / valor, y al igual que cualquier objeto en Python, son comparables indistintamente

Julio Cezar Silva
fuente