Necesito verificar si una lista es un subconjunto de otra; todo lo que busco es un retorno booleano.
¿Prueba la igualdad en la lista más pequeña después de una intersección es la forma más rápida de hacer esto? El rendimiento es de suma importancia dada la cantidad de conjuntos de datos que deben compararse.
Agregar más hechos basados en discusiones:
¿Alguna de las listas será la misma para muchas pruebas? Lo hace como uno de ellos es una tabla de búsqueda estática.
¿Tiene que ser una lista? No es así: la tabla de búsqueda estática puede ser cualquier cosa que funcione mejor. El dinámico es un dict del que extraemos las claves para realizar una búsqueda estática.
¿Cuál sería la solución óptima dado el escenario?
Respuestas:
La función de rendimiento que Python proporciona para esto es
set.issubset
. Sin embargo, tiene algunas restricciones que no aclaran si es la respuesta a su pregunta.Una lista puede contener elementos varias veces y tiene un orden específico. Un conjunto no. Además, los conjuntos solo funcionan en objetos hashaable .
¿Está preguntando sobre un subconjunto o subsecuencia (lo que significa que querrá un algoritmo de búsqueda de cadenas)? ¿Alguna de las listas será la misma para muchas pruebas? ¿Cuáles son los tipos de datos contenidos en la lista? Y para el caso, ¿tiene que ser una lista?
Su otra publicación se cruza con un dict y la lista hizo los tipos más claros y recibió una recomendación para usar vistas de clave de diccionario para su funcionalidad de conjunto. En ese caso, se sabía que funcionaba porque las teclas del diccionario se comportaban como un conjunto (tanto que antes de tener conjuntos en Python usábamos diccionarios). Uno se pregunta cómo el problema se volvió menos específico en tres horas.
fuente
fuente
set(a).issubset(b)
porque en este caso solo se conviertea
en conjunto, pero nob
, lo que ahorra tiempo. Puede usartimeit
para comparar el tiempo consumido en dos comandos. Por ejemplo,timeit.repeat('set(a)<set(b)', 'a = [1,3,5]; b = [1,3,5,7]', number=1000)
ytimeit.repeat('set(a).issubset(b)', 'a = [1,3,5]; b = [1,3,5,7]', number=1000)
issubset
hace es verificar si el argumento es unset
/frozenset
, y si no lo es, lo convierte en temporalset
para comparar, ejecuta el cheque y luego tira el temporalset
. Las diferencias de tiempo (si las hubiera) serían un factor de pequeñas diferencias en los costos de búsqueda de LEGB (encontrarset
una segunda vez es más costoso que la búsqueda de atributos en una existenteset
), pero es principalmente un lavado para entradas lo suficientemente grandes.Explicación: Generador que crea booleanos recorriendo la lista
one
comprobando si ese elemento está en la listatwo
.all()
devuelveTrue
si cada elemento es verdadero, de lo contrarioFalse
.También hay una ventaja que
all
devuelve False en la primera instancia de un elemento faltante en lugar de tener que procesar cada elemento.fuente
set(one).issubset(set(two))
es una gran solución. Con la solución que publiqué, debería poder usarla con cualquier objeto si tienen definidos los operadores de comparación adecuados.all
un cortocircuito correctamente, el segundo realizará todas las comprobaciones incluso si fuera claro desde la primera comprobación que la prueba fallaría. Simplemente suelte los corchetes para obtenerall(x in two for x in one)
.Asumiendo que los artículos son hashable
Si no le importan los elementos duplicados, por ejemplo.
[1, 2, 2]
y[1, 2]
luego solo usa:.issubset
Será la forma más rápida de hacerlo. Verificar la longitud antes de la pruebaissubset
no mejorará la velocidad porque todavía tiene elementos O (N + M) para recorrer y verificar.fuente
Una solución más sería usar a
intersection
.La intersección de los conjuntos contendría de
set one
(O)
fuente
Si list1 está en la lista 2:
(x in two for x in one)
genera una lista deTrue
.cuando hacemos un
set(x in two for x in one)
solo tiene un elemento (Verdadero).fuente
La teoría de conjuntos es inapropiada para las listas ya que los duplicados darán como resultado respuestas incorrectas utilizando la teoría de conjuntos.
Por ejemplo:
no tiene sentido. Sí, da una respuesta falsa, pero esto no es correcto ya que la teoría de conjuntos solo compara: 1,3,5 versus 1,3,4,5. Debe incluir todos los duplicados.
En su lugar, debe contar cada aparición de cada elemento y hacer un chequeo mayor que igual. Esto no es muy costoso, ya que no está utilizando operaciones O (N ^ 2) y no requiere ordenación rápida.
Luego de ejecutar esto obtienes:
fuente
Como nadie ha considerado comparar dos cadenas, aquí está mi propuesta.
Por supuesto, es posible que desee comprobar si la tubería ("|") no forma parte de ninguna de las listas y tal vez eligió automáticamente otro carácter, pero se le ocurrió la idea.
Usar una cadena vacía como separador no es una solución ya que los números pueden tener varios dígitos ([12,3]! = [1,23])
fuente
Disculpe si llego tarde a la fiesta. ;)
Para verificar si uno
set A
es un subconjunto deset B
,Python
tieneA.issubset(B)
yA <= B
. Solo funcionaset
y funciona muy bien PERO se desconoce la complejidad de la implementación interna. Referencia: https://docs.python.org/2/library/sets.html#set-objectsSe me ocurrió un algoritmo para verificar si
list A
es un subconjunto de loslist B
siguientes comentarios.sort
primero ambas listas antes de comparar elementos para calificar para el subconjunto.break
laloop
cuando el valor del elemento de la segunda listaB[j]
es mayor que el valor del elemento de la primera listaA[i]
.last_index_j
se utiliza para comenzar deloop
nuevolist B
donde lo dejó por última vez. Ayuda a evitar comenzar las comparaciones desde el principiolist B
(que es, como puede suponer innecesario, comenzarlist B
desde elindex 0
siguienteiterations
).La complejidad será
O(n ln n)
cada una para ordenar ambas listas yO(n)
para verificar el subconjunto.O(n ln n) + O(n ln n) + O(n) = O(n ln n)
.El código tiene muchas
print
declaraciones para ver qué sucede en cada unoiteration
de losloop
. Estos son solo para entender.Compruebe si una lista es un subconjunto de otra lista
Salida
fuente
El siguiente código verifica si un conjunto dado es un "subconjunto apropiado" de otro conjunto
fuente
En python 3.5 puedes hacer una
[*set()][index]
para obtener el elemento. Es una solución mucho más lenta que otros métodos.o solo con len y set
fuente
Así es como sé si una lista es un subconjunto de otra, la secuencia me importa en mi caso.
fuente
La mayoría de las soluciones consideran que las listas no tienen duplicados. En caso de que sus listas tengan duplicados, puede intentar esto:
Asegura que la sublista nunca tenga elementos diferentes a la lista o una mayor cantidad de un elemento común.
fuente
Si está preguntando si una lista está "contenida" en otra lista, entonces:
Si está preguntando si cada elemento de la lista A tiene el mismo número de elementos coincidentes en la lista B, intente:
fuente
Si
a2 is subset of a1
, entoncesLength of set(a1 + a2) == Length of set(a1)
fuente