Como Ordenar un Diccionario de objetos en Python 3

Python me ha causado una buena impresión en la mayoría de las veces que he aprendido algo o cuando he necesitado alguna «cosa» particular para hacer en algún proyecto. Hace unos días tuve la necesidad de crear un diccionario de objetos de un modelo y ordenarlo por una propiedad dentro de esos objetos. La verdad ordenar un array que contiene objetos de un modelo en python es bastante sencillo.

Como Ordenar un Diccionario de objetos en Python

Las listas o diccionarios son estrucutras de datos particulares de python, se asemejan a los arrays o arreglos de otros lenguajes pero en python (todo en python, creo que es justo decir) están supercargados de características que le hacen la vida mas sencilla a los programadores. Pueden parecer mas complejos, pero en realidad son mas sofisticados y útiles.

Hace algunos días necesité crear un Modelo en Django al que llamaremos Colector, que debía registrar datos de varias fuentes (websockets) y grabarlos en la base de datos (el modelo), pero como era necesario tener el último estado de una serie de «productos» y su frecuencia de actualización era de menos de un segundo y eran cientos o miles de productos, no se podía estar haciendo cientos o miles de consultas a la tabla para extraer «de nuevo el último registro» de cada «producto», la solución mas sencilla era mantener en memoria (un arreglo o diccionario) el último estado de cada producto. El array o diccionario tenía una estructura como sigue:

monitor = {
  "tienda_1" : [
     {'producto1': <colector: producto="producto1",
                              modelo="modelo1" 
                              ultimop=210000.00,
                              volumen=3450.00, 
                              created_at=2019-07-05 23:08:00 >
     },
     {'producto2': <colector: producto="producto2",
                              modelo="modelo1" 
                              ultimop=130000.00,
                              volumen=1450.00, 
                              created_at=2019-07-05 23:08:01 >
     },
     {'producto3': <colector: producto="producto3",
                              modelo="modelo3" 
                              ultimop=1100.00,
                              volumen=451450.00, 
                              created_at=2019-07-05 23:07:01 >
     },
   ],
  "tienda_2" : [
     {'unico': <colector: producto="unico",
                          modelo="modelounico" 
                          ultimop=1000.00,
                          volumen=3450.00, 
                          created_at=2019-07-05 23:08:10 >
     },
   ]
}

Para mantener el último estado de un producto en el diccionario, se necesita recibir los datos del socket o de la fuente y registrarlo en el modelo:

def on_message(ws, message):
    data_message  = json.loads(message)
    # Se crea el objeto en el Modelo y se graba la info
    tx = Colector()
    tx.producto   = data_message['payload'][0]['p']
    tx.modelo     = data_message['payload'][0]['m']
    tx.ultimop    = data_message['payload'][0]['l']
    tx.volumen    = data_message['payload'][0]['v']
    tx.created_at = timezone.now()
    tx.save()

Una vez que los datos están en el objeto tx y se han grabado podemos agregarlos al diccionario

   monitor['tienda_1'].update({tx.producto: tx})

Pero si necesitamos generar un listado de los productos de la tienda_1 con los precio mas reciente que se ha obtenido del websocket pero ordenados por el volumen de ese producto podríamos creer que estamos en un aprieto. Podríamos pensar que necesitamos hacer un query nuevo, o generar de otra forma el array, etc. Pero Python tiene magia, me atrevo a decir, y por esto entiendo que sea uno de los lenguajes mas usados en Inteligencia Artificial, Mineria de Datos y Machine Learning.

Para generar el reporte por tienda y ordenar el array de objetos por el campo «volumen» de cada objeto , podemos hacer lo siguiente:

    for tienda in monitor :
        lista_ordenada = sorted(monitor[tienda].items(), key=lambda x: x[1].volumen, reverse=True)
        for item in lista_ordenada:
            print( item[1].producto, 
                   item[1].modelo,
                   item[1].ultimop,
                   item[1].volumen
                 )
        print()

La salida que se generaría por este código sería algo muy parecido a esto:

producto3 modelo3 1100.00 451450.00
producto1 modelo1 210000.00 3450.00
producto2 modelo1 130000.00 1450.00

unico modelounico 1000.00 3450.00

en otros lenguajes habría que desarrollar un pequeño programa para que hiciera el ordenamiento, o tal vez se buscaría otro enfoque que no complicara el programa, pero en python se hace on SOLO UNA linea de código:

lista_ordenada = sorted(array.items(), key=lambda x: x[1].column, reverse=True)

No se a ustedes pero a mi, esto me pareció una característica increíble del lenguaje. Por esto me encanta Python.

This entry was posted in Python and tagged , , , . Bookmark the permalink.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *


*