Recientemente noté que cuando estoy convirtiendo list
a, set
el orden de los elementos cambia y se ordena por carácter.
Considere este ejemplo:
x=[1,2,20,6,210]
print x
# [1, 2, 20, 6, 210] # the order is same as initial order
set(x)
# set([1, 2, 20, 210, 6]) # in the set(x) output order is sorted
Mis preguntas son:
- ¿Por qué está pasando esto?
- ¿Cómo puedo realizar operaciones de set (especialmente Set Difference) sin perder el orden inicial?
unique = list(dict.fromkeys([1, 2, 1]).keys())
. Esto funciona porque losdict
s conservan el orden de inserción ahora.Respuestas:
A
set
es una estructura de datos desordenada, por lo que no conserva el orden de inserción.Depende de sus requisitos. Si tiene una lista normal y desea eliminar algún conjunto de elementos conservando el orden de la lista, puede hacerlo con una lista de comprensión:
Si necesita una estructura de datos que admita tanto las pruebas de membresía rápidas como la preservación del orden de inserción , puede usar las claves de un diccionario de Python, que a partir de Python 3.7 garantiza preservar el orden de inserción:
b
realmente no es necesario pedirlo aquí, también podría usar unset
. Tenga en cuenta quea.keys() - b.keys()
devuelve la diferencia establecida como aset
, por lo que no conservará el orden de inserción.En versiones anteriores de Python, puede usar
collections.OrderedDict
en su lugar:fuente
None
es un idioma único garantizado. En CPython, el costo real es solo el puntero (aunque ese costo siempre está ahí, pero para un dict, casi puede considerarNone
y otros singletons o referencias compartidas "gratis"), por lo que una palabra de máquina, probablemente 8 bytes en computadoras modernas . Pero sí, no es tan eficiente en cuanto al espacio como podría serlo un conjunto.dict.fromkeys([1, 2, 1]).keys()
porque losdict
s regulares también conservan el orden.En Python 3.6,hay otra solución para Python 2 y 3:set()
ahora debería mantener el orden, perofuente
x.index
se llama, se realiza una búsqueda lineal. Si está de acuerdo con la complejidad cuadrática, no hay razón para usar aset
en primer lugar.set()
no está ordenado en Python 3.6, ni siquiera como un detalle de implementación, estás pensando endict
sint
a menudo se hacen hash a sí mismos stackoverflow.com/questions/45581901/…x=[1,2,-1,20,6,210]
convertirlo en un conjunto. Verá que no está ordenado en absoluto, probado en Python 3.6.Respondiendo a su primera pregunta, un conjunto es una estructura de datos optimizada para operaciones de conjuntos. Como un conjunto matemático, no impone ni mantiene ningún orden particular de los elementos. El concepto abstracto de un conjunto no impone el orden, por lo que no se requiere la implementación. Cuando crea un conjunto a partir de una lista, Python tiene la libertad de cambiar el orden de los elementos según las necesidades de la implementación interna que utiliza para un conjunto, que puede realizar operaciones de conjunto de manera eficiente.
fuente
eliminar duplicados y preservar el orden mediante la siguiente función
revisa este enlace
fuente
En matemáticas, hay conjuntos y conjuntos ordenados (osets).
En Python, solo los conjuntos se implementan directamente. Podemos emular osets con claves de dictado regulares ( 3.7+ ).
Dado
Código
Manifestación
Se eliminan las réplicas, se conserva el orden de inserción.
Operaciones tipo set en claves dictadas.
Detalles
Nota: una estructura desordenada no excluye los elementos ordenados. Más bien, el orden mantenido no está garantizado. Ejemplo:
Uno puede estar satisfecho al descubrir que una lista y conjunto múltiple (mset) son dos más fascinantes, estructuras de datos matemáticos:
Resumen
* Un multiset se puede emular indirectamente con
collections.Counter()
un mapeo de multiplicidades (recuentos) similar a un dictado .fuente
Como se indica en otras respuestas, los conjuntos son estructuras de datos (y conceptos matemáticos) que no conservan el orden de los elementos:
Sin embargo, al usar una combinación de conjuntos y diccionarios, es posible que pueda lograr lo que quiera; intente usar estos fragmentos:
fuente
Sobre la base de la respuesta de Sven, encontré que el uso de collections.OrderedDict me ayudó a lograr lo que quieres y además me permite agregar más elementos al dict:
Si desea agregar elementos pero aún así tratarlo como un conjunto, puede hacer lo siguiente:
Y puede realizar una operación como z.keys () en el dict y obtener el conjunto:
fuente
list(z.keys())
para obtener la salida de la lista.Una implementación del concepto de puntuación más alta anterior que lo devuelve a una lista:
Probado (brevemente) en Python 3.6 y Python 2.7.
fuente
En caso de que tenga una pequeña cantidad de elementos en sus dos listas iniciales en las que desee realizar una operación de diferenciación de conjuntos, en lugar de usar lo
collections.OrderedDict
que complica la implementación y lo hace menos legible, puede usar:Su complejidad temporal no es tan buena, pero es ordenada y fácil de leer.
fuente
Es interesante que la gente siempre use "problema del mundo real" para bromear sobre la definición en ciencia teórica.
Si el conjunto tiene orden, primero debe resolver los siguientes problemas. Si su lista tiene elementos duplicados, ¿cuál debería ser el orden cuando la convierta en un conjunto? ¿Cuál es el orden si unimos dos conjuntos? ¿Cuál es el orden si intersecamos dos conjuntos con diferente orden en los mismos elementos?
Además, el conjunto es mucho más rápido en la búsqueda de una clave en particular, lo cual es muy bueno en el funcionamiento de conjuntos (y es por eso que necesita un conjunto, pero no una lista).
Si realmente le importa el índice, guárdelo como una lista. Si aún desea realizar la operación de conjunto en los elementos en muchas listas, la forma más sencilla es crear un diccionario para cada lista con las mismas claves en el conjunto junto con un valor de lista que contiene todo el índice de la clave en la lista original.
fuente
He aquí una forma sencilla de hacerlo:
fuente