itertools.groupby: agrupa datos ordenados correctamente

Publicado el: 30/08/2026
Tempo de leitura: 2 minutos
A person reads 'Python for Unix and Linux System Administration' indoors.

itertools.groupby() agrupa elementos consecutivos que producen la misma clave. Es lazy, consume la entrada solo cuando hace falta y puede procesar streams grandes sin cargar todos los datos en memoria. Su comportamiento no es igual al GROUP BY de SQL: claves iguales que no son adyacentes generan grupos separados.

Esta guía explica ordenación previa, subiteradores compartidos, agregaciones streaming, objetos, grupos anidados y errores frecuentes.

Ejemplo básico

from itertools import groupby

valores = [1, 1, 2, 2, 2, 3]
for clave, grupo in groupby(valores):
    print(clave, list(grupo))

Cada secuencia consecutiva de valores iguales se convierte en un grupo.

La adyacencia es la regla principal

valores = [1, 2, 1]
print([(clave, list(grupo)) for clave, grupo in groupby(valores)])

El valor 1 aparece dos veces porque está separado. Ordena primero cuando quieras reunir todas las claves iguales.

Ordenar con la misma clave

registros.sort(key=lambda item: item["categoria"])
for categoria, grupo in groupby(registros, key=lambda item: item["categoria"]):
    elementos = list(grupo)
    procesar(categoria, elementos)

La clave de ordenación y la de agrupación deben representar la misma regla.

Los grupos comparten el iterador

Cada grupo es un subiterador conectado al iterador principal. Al avanzar a la siguiente clave, el grupo anterior deja de estar disponible. Materialízalo de inmediato si necesitas conservarlo.

for clave, grupo in groupby(datos, key=obtener_clave):
    elementos = list(grupo)
    guardar(clave, elementos)

Agregación streaming

for categoria, grupo in groupby(registros, key=lambda fila: fila.categoria):
    total = sum(fila.importe for fila in grupo)
    print(categoria, total)

El grupo se consume directamente y mantiene bajo el uso de memoria.

Contar sin crear listas

for clave, grupo in groupby(datos, key=obtener_clave):
    cantidad = sum(1 for _ in grupo)
    print(clave, cantidad)

Agrupar objetos

from operator import attrgetter

pedidos.sort(key=attrgetter("cliente_id"))
for cliente_id, grupo in groupby(pedidos, key=attrgetter("cliente_id")):
    procesar_pedidos(cliente_id, grupo)

attrgetter puede expresar la intención mejor que varias lambdas repetidas.

Entradas ya ordenadas

Resultados SQL con ORDER BY, archivos ordenados y streams monotónicos son casos ideales. groupby permite agregarlos de forma incremental.

Diccionario frente a groupby

Un diccionario de listas agrupa sin importar el orden, pero conserva todos los elementos. groupby usa poca memoria, aunque necesita claves adyacentes.

Normalización de texto

nombres.sort(key=str.casefold)
for clave, grupo in groupby(nombres, key=str.casefold):
    print(clave, list(grupo))

Usa la misma normalización al ordenar y agrupar. Para texto humano puede ser necesario considerar locale.

Agrupación anidada

filas.sort(key=lambda fila: (fila.pais, fila.ciudad))
for pais, grupo_pais in groupby(filas, key=lambda fila: fila.pais):
    filas_pais = list(grupo_pais)
    for ciudad, grupo_ciudad in groupby(filas_pais, key=lambda fila: fila.ciudad):
        procesar(pais, ciudad, grupo_ciudad)

El grupo exterior se materializa porque todos los subgrupos comparten el iterador subyacente.

Errores comunes

  • Esperar que claves iguales no adyacentes se unan.
  • Ordenar y agrupar con claves incompatibles.
  • Guardar el subiterador para consumirlo después.
  • Convertir todos los grupos en listas sin necesidad.
  • Usar una función de clave con efectos secundarios.

Buenas prácticas

Documenta el requisito de orden, mantén las funciones de clave puras, consume cada grupo antes de avanzar y materializa solo cuando sea necesario. Consulta también las guías internas de itertools en Python y itertools.pairwise.

Conclusión

itertools.groupby es ideal para segmentar secuencias ordenadas y crear agregaciones de bajo consumo de memoria. Comprender la adyacencia y los iteradores compartidos evita resultados incorrectos.

Fuentes externas

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Contenido del artículo

    Artículos relacionados

    Close-up of hands typing on a laptop keyboard, Python book in sight, coding in progress.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    itertools.accumulate: sumas y estados acumulados

    Aprende itertools.accumulate en Python para sumas, saldos, récords, transiciones de estado y pipelines lazy eficientes.

    Ler mais

    Tempo de leitura: 2 minutos
    30/08/2026
    A person in a hoodie coding on dual monitors, depicting cybersecurity and hacking themes.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    contextlib.chdir: riesgos al cambiar directorios

    Aprende contextlib.chdir en Python, sus riesgos con estado global y concurrencia y cuándo usar pathlib o subprocess cwd.

    Ler mais

    Tempo de leitura: 3 minutos
    30/08/2026
    A person typing on a laptop with a Python programming book visible, capturing technology and learning.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    nullcontext en Python: contextos opcionales

    Usa nullcontext en Python para unificar archivos, locks, transacciones, sesiones y recursos prestados sin duplicar ramas.

    Ler mais

    Tempo de leitura: 4 minutos
    30/08/2026
    Vivid close-up of a python resting among autumn leaves, showcasing its intricate patterns.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    contextlib.aclosing: cierra generadores async

    Aprende contextlib.aclosing en Python para cerrar generadores async tras break, return, excepciones, cancelación y consumo parcial.

    Ler mais

    Tempo de leitura: 5 minutos
    30/08/2026
    High-angle view of woman coding on a laptop, with a Python book nearby. Ideal for programming and tech content.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    weakref.finalize: limpieza sin retener objetos

    Aprende weakref.finalize en Python para limpiar recursos sin retener objetos, usando alive, detach, shutdown y cierre explícito seguro.

    Ler mais

    Tempo de leitura: 5 minutos
    30/08/2026
    A developer typing code on a laptop with a Python book beside in an office.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    SimpleNamespace: objetos ligeros con atributos

    Aprende SimpleNamespace en Python para crear objetos ligeros por atributos, convertir diccionarios, copiar y elegir modelos tipados.

    Ler mais

    Tempo de leitura: 5 minutos
    29/08/2026