OrderedDict

 OrderedDict es una subclase de diccionario que mantiene el orden de inserción de los elementos. Vamos a verlo en detalle:

¿Qué es OrderedDict?

Es un diccionario especial que recuerda el orden en que se agregaron los elementos, a diferencia de un diccionario normal que no garantiza ningún orden específico.

python
from collections import OrderedDict

# Crear un OrderedDict
od = OrderedDict()
od['a'] = 1
od['b'] = 2
od['c'] = 3

print(od)  # OrderedDict([('a', 1), ('b', 2), ('c', 3)])

Diferencias con dict normal

Python 3.6 y anteriores:

python
# Dict normal (no garantiza orden)
normal_dict = {}
normal_dict['z'] = 1
normal_dict['a'] = 2
normal_dict['m'] = 3
print(normal_dict)  # Podría mostrar en cualquier orden

# OrderedDict (mantiene orden)
ordered_dict = OrderedDict()
ordered_dict['z'] = 1
ordered_dict['a'] = 2
ordered_dict['m'] = 3
print(ordered_dict)  # Siempre: OrderedDict([('z', 1), ('a', 2), ('m', 3)])

Python 3.7+:

A partir de Python 3.7, los diccionarios normales también mantienen el orden de inserción, pero OrderedDict sigue siendo útil por sus métodos adicionales.

Métodos útiles de OrderedDict

1. move_to_end()

Mueve un elemento existente al principio o final del diccionario.

python
od = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 4)])

# Mover 'b' al final
od.move_to_end('b')
print(od)  # OrderedDict([('a', 1), ('c', 3), ('d', 4), ('b', 2)])

# Mover 'c' al principio
od.move_to_end('c', last=False)
print(od)  # OrderedDict([('c', 3), ('a', 1), ('d', 4), ('b', 2)])

2. popitem()

Elimina y retorna un elemento. Puede ser el último o el primero.

python
od = OrderedDict([('a', 1), ('b', 2), ('c', 3)])

# Eliminar el último elemento (por defecto)
last_item = od.popitem()
print(last_item)  # ('c', 3)
print(od)         # OrderedDict([('a', 1), ('b', 2)])

# Eliminar el primer elemento
first_item = od.popitem(last=False)
print(first_item)  # ('a', 1)
print(od)          # OrderedDict([('b', 2)])

Casos de uso comunes

1. Implementar una caché LRU (Least Recently Used)

python
from collections import OrderedDict

class LRUCache:
    def __init__(self, capacity):
        self.cache = OrderedDict()
        self.capacity = capacity
    
    def get(self, key):
        if key not in self.cache:
            return -1
        # Mover al final (más reciente)
        self.cache.move_to_end(key)
        return self.cache[key]
    
    def put(self, key, value):
        if key in self.cache:
            # Actualizar y mover al final
            self.cache.move_to_end(key)
        self.cache[key] = value
        # Si excede capacidad, eliminar el más antiguo
        if len(self.cache) > self.capacity:
            self.cache.popitem(last=False)

# Uso
cache = LRUCache(2)
cache.put(1, 'a')
cache.put(2, 'b')
print(cache.get(1))  # 'a'
cache.put(3, 'c')    # Elimina la clave 2 (menos usada recientemente)
print(cache.get(2))  # -1 (no encontrado)

2. Procesar datos en orden específico

python
# Procesar elementos en el orden en que fueron agregados
tasks = OrderedDict()
tasks['leer'] = 'pendiente'
tasks['escribir'] = 'pendiente'
tasks['revisar'] = 'pendiente'

for task, status in tasks.items():
    print(f"Tarea: {task}, Estado: {status}")
# Salida en el orden de inserción:
# Tarea: leer, Estado: pendiente
# Tarea: escribir, Estado: pendiente
# Tarea: revisar, Estado: pendiente

3. Mantener orden al eliminar duplicados

python
def eliminar_duplicados_mantener_orden(lista):
    return list(OrderedDict.fromkeys(lista))

numeros = [3, 1, 2, 1, 4, 3, 5, 2]
resultado = eliminar_duplicados_mantener_orden(numeros)
print(resultado)  # [3, 1, 2, 4, 5]

Comparación con dict normal (Python 3.7+)

CaracterísticadictOrderedDict
Mantiene orden
move_to_end()
popitem(last=False)
Igualdad considera orden
python
# En OrderedDict, el orden importa para la igualdad
od1 = OrderedDict([('a', 1), ('b', 2)])
od2 = OrderedDict([('b', 2), ('a', 1)])

print(od1 == od2)  # False (orden diferente)

# En dict normal, el orden no importa
d1 = {'a': 1, 'b': 2}
d2 = {'b': 2, 'a': 1}
print(d1 == d2)    # True (mismos pares clave-valor)

Conclusión

OrderedDict es especialmente útil cuando:

  • Necesitas métodos como move_to_end() o popitem(last=False)

  • Quieres garantizar compatibilidad con versiones anteriores de Python

  • La igualdad debe considerar el orden de los elementos

  • Implementas estructuras como cachés LRU

En Python 3.7+, para casos simples de mantener orden, un diccionario normal puede ser suficiente, pero OrderedDict sigue ofreciendo funcionalidades adicionales valiosas.

Comentarios

Entradas populares de este blog

¿Qué es un Closure?

Calculadora de edad

Funciones en Python: con y sin paréntesis