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?

4 tipos de colecciones de datos más

Funciones en Python: con y sin paréntesis