¿Es la forma correcta de inicializar un OrderedDict usando su constructor de modo que conserve el orden de los datos iniciales?

124

¿Cuál es la forma correcta de inicializar un diccionario ordenado (OD) para que conserve el orden de los datos iniciales?

from collections import OrderedDict

# Obviously wrong because regular dict loses order
d = OrderedDict({'b':2, 'a':1}) 

# An OD is represented by a list of tuples, so would this work?
d = OrderedDict([('b',2), ('a', 1)])

# What about using a list comprehension, will 'd' preserve the order of 'l'
l = ['b', 'a', 'c', 'aa']
d = OrderedDict([(i,i) for i in l])

Pregunta:

  • ¿Se OrderedDictpreservará el orden de una lista de tuplas, o una tupla de tuplas o una tupla de listas o una lista de listas, etc., aprobadas en el momento de la inicialización (segundo y tercer ejemplo anteriores)?

  • ¿Cómo se verifica si OrderedDictrealmente se mantiene un orden? Como a dicttiene un orden impredecible, ¿qué sucede si mis vectores de prueba tienen el mismo orden inicial que el orden impredecible de un dict? Por ejemplo, si en lugar de d = OrderedDict({'b':2, 'a':1})escribir d = OrderedDict({'a':1, 'b':2}), puedo concluir erróneamente que se conserva el orden. En este caso, descubrí que a dictestá ordenado alfabéticamente, pero eso puede no ser siempre cierto. ¿Cuál es una forma confiable de usar un contraejemplo para verificar si una estructura de datos conserva el orden o no, a menos que intente probar vectores repetidamente hasta que uno se rompa?

PD: solo dejaré esto aquí como referencia : "El constructor OrderedDict y el método update () aceptan argumentos de palabras clave, pero su orden se pierde porque la función de Python llama a la semántica los argumentos de palabras clave de paso usando un diccionario regular sin ordenar"

PPS: Con suerte, en el futuro, OrderedDict también preservará el orden de los kwargs (ejemplo 1): http://bugs.python.org/issue16991

hacer clic
fuente
10
Es vagamente irónico que inicializar un OrderedDict con un dict (no vacío) sea algo incorrecto ... podría decirse que debería resultar en una Advertencia ya que probablemente viola la intención del usuario.
smci
3
Después de python3.6, OrderDict(b=2, a=1)también es una forma adecuada. Ver PEP 468 .
IvanaGyro

Respuestas:

90

El OrderedDict conservará cualquier pedido al que tenga acceso. La única forma de pasarle los datos ordenados para que se inicialice es pasar una lista (o, más generalmente, una iterable) de pares clave-valor, como en los últimos dos ejemplos. Como dice la documentación a la que se vinculó, OrderedDict no tiene acceso a ningún orden cuando pasa argumentos de palabras clave o un argumento dict, ya que cualquier orden allí se elimina antes de que el constructor OrderedDict lo vea.

Tenga en cuenta que usar una lista de comprensión en su último ejemplo no cambia nada. No hay diferencia entre OrderedDict([(i,i) for i in l])y OrderedDict([('b', 'b'), ('a', 'a'), ('c', 'c'), ('aa', 'aa')]). La comprensión de la lista se evalúa y crea la lista y se pasa; OrderedDict no sabe nada sobre cómo se creó.

BrenBarn
fuente
74
# An OD is represented by a list of tuples, so would this work?
d = OrderedDict([('b', 2), ('a', 1)])

Sí, eso funcionará. Por definición, una lista siempre se ordena de la forma en que se representa. Esto también se aplica a la comprensión de la lista, la lista generada es de la misma manera que se proporcionaron los datos (es decir, la fuente de una lista será determinista, se obtendrá de una fuente seto dictno tanto).

¿Cómo se hace para verificar si OrderedDictrealmente se mantiene un orden? Dado que un dict tiene un orden impredecible, ¿qué pasa si mis vectores de prueba tienen el mismo orden inicial que el orden impredecible de un dict ?. Por ejemplo, si en lugar de d = OrderedDict({'b':2, 'a':1})escribir d = OrderedDict({'a':1, 'b':2}), puedo concluir erróneamente que se conserva el orden. En este caso, descubrí que a dictes orden alfabético, pero eso puede no ser siempre cierto. es decir, cuál es una manera confiable de usar un ejemplo de contador para verificar si una estructura de datos conserva el orden o no prueba los vectores de prueba repetidamente hasta que uno se rompe.

Mantiene su lista de fuentes de 2 tuplas como referencia y la usa como datos de prueba para sus casos de prueba cuando realiza pruebas unitarias. Iterar a través de ellos y asegurar que se mantenga el orden.

metatoaster
fuente
Sobre la verificación del pedido: ¿Cómo me aseguro de que mi 2-tupla romperá el orden del dict si es impredecible? Esta es una pregunta genérica sobre cualquier estructura de datos, quizás debería separarla de esta pregunta.
haga clic en
1
No se puede romper de manera determinista algo que no sea de naturaleza determinista.
metatoaster
1
Entonces, ¿cuál es el enfoque correcto para probar tales cosas? ¿Sigues intentándolo indefinidamente? El orden es impredecible para los programadores, pero como se trata de un mapa hash, sigue un "algoritmo" y una prueba correcta debería intentar contrarrestar eso.
haga clic en
2
Ver __hash__. Específicamente sobre el strtipo.
metatoaster
Por definición, una lista siempre se ordena de la forma en que se representa. Esta fue una declaración clave para mí. Decidí simplemente usar una lista de 2 tuplas para mi básico OrderedDictpara no tener la sobrecarga de convertir una lista a un OrderedDict. Simplemente recorro los elementos como una lista en lugar de un diccionario.
Bobort