itertools.groupby: agrupe dados ordenados corretamente

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

itertools.groupby() agrupa elementos consecutivos que produzem a mesma chave. Ele trabalha de forma preguiçosa, consome o iterável apenas conforme necessário e pode processar grandes fluxos sem carregar todos os dados na memória. Porém, seu comportamento é diferente de um GROUP BY de banco de dados: valores iguais que não estejam adjacentes formam grupos separados.

Neste guia, você aprenderá a ordenar dados antes do agrupamento, consumir os subiteradores corretamente, agregar registros em streaming, trabalhar com objetos e evitar os erros mais comuns.

Primeiro exemplo

from itertools import groupby

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

O resultado contém um grupo para cada sequência consecutiva de valores iguais.

A regra da adjacência

valores = [1, 2, 1]
print([(k, list(g)) for k, g in groupby(valores)])

O valor 1 aparece em dois grupos, porque os elementos iguais não estão juntos. Para reunir todas as ocorrências por chave, ordene primeiro quando isso fizer sentido.

Ordenar pela mesma chave

registros = [
    {"categoria": "b", "valor": 4},
    {"categoria": "a", "valor": 2},
    {"categoria": "b", "valor": 7},
]

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

A função usada na ordenação deve ser compatível com a função de chave do agrupamento. Caso contrário, uma mesma chave pode reaparecer em grupos separados.

Os grupos compartilham o iterador

Cada grupo é um subiterador ligado ao iterador principal. Quando o loop avança para a próxima chave, o grupo anterior deixa de estar disponível. Materialize-o imediatamente quando precisar conservar seus itens.

for chave, grupo in groupby(dados, key=obter_chave):
    itens = list(grupo)
    processar(chave, itens)

Agregação sem materializar tudo

for categoria, grupo in groupby(registros, key=lambda r: r.categoria):
    total = sum(item.valor for item in grupo)
    print(categoria, total)

Nesse caso, o grupo é consumido diretamente por sum. Isso reduz memória e combina bem com arquivos ordenados, logs e resultados de consultas.

Contagem por grupo

for chave, grupo in groupby(dados, key=obter_chave):
    quantidade = sum(1 for _ in grupo)
    print(chave, quantidade)

O padrão evita criar uma lista apenas para usar len.

Agrupando objetos

from operator import attrgetter

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

operator.attrgetter pode deixar a intenção mais clara que uma lambda repetida.

Dados já ordenados

Quando uma consulta SQL usa ORDER BY, um arquivo é produzido em ordem ou um pipeline garante monotonicidade, groupby pode agregar em streaming. Esse é um dos seus melhores casos de uso.

Diferença para um dicionário

Um dicionário de listas agrupa independentemente da ordem, mas precisa manter todas as coleções em memória. groupby preserva o fluxo e usa pouca memória, desde que os dados estejam adjacentes por chave.

Diferença para pandas

pandas.DataFrame.groupby oferece operações vetorizadas, índices e agregações tabulares. itertools.groupby é mais leve e apropriado para iteradores Python, streams e transformações da biblioteca padrão.

Normalização da chave

nomes.sort(key=lambda nome: nome.casefold())
for chave, grupo in groupby(nomes, key=lambda nome: nome.casefold()):
    print(chave, list(grupo))

Use a mesma normalização para ordenar e agrupar. Para texto humano, considere locale e regras de Unicode.

Grupos aninhados

dados.sort(key=lambda r: (r.pais, r.cidade))
for pais, grupo_pais in groupby(dados, key=lambda r: r.pais):
    itens_pais = list(grupo_pais)
    for cidade, grupo_cidade in groupby(itens_pais, key=lambda r: r.cidade):
        processar(pais, cidade, grupo_cidade)

Materializar o grupo externo pode ser necessário porque o iterador principal é compartilhado.

Erros comuns

  • Esperar que chaves iguais não adjacentes sejam reunidas.
  • Ordenar com uma chave e agrupar com outra.
  • Guardar o subiterador para consumir mais tarde.
  • Converter todos os grupos em listas sem necessidade.
  • Executar a função de chave com efeitos colaterais.

Boas práticas

Documente se a entrada precisa estar ordenada, mantenha a função de chave pura, consuma cada grupo antes de avançar e escolha entre streaming e materialização conscientemente. Veja também os guias internos sobre itertools no Python e itertools.pairwise.

Conclusão

itertools.groupby é uma ferramenta eficiente para segmentar sequências ordenadas e realizar agregações preguiçosas. Entender a adjacência e o compartilhamento do iterador evita resultados incorretos e permite pipelines de baixo consumo de memória.

Fontes externas

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Conteúdo do artigo

    Artigos relacionados

    Código binário representando bytearray.resize no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    bytearray.resize: redimensione buffers com segurança

    Aprenda bytearray.resize no Python para expandir e reduzir buffers com segurança, limites e compatibilidade.

    Ler mais

    Tempo de leitura: 5 minutos
    24/10/2026
    Código Python em notebook para filtrar valores None
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    operator.is_none: filtre None sem perder falsy

    Aprenda operator.is_none e is_not_none para filtrar None sem remover valores falsy válidos no Python.

    Ler mais

    Tempo de leitura: 4 minutos
    23/10/2026
    Código Python em um notebook para criar dataclasses dinâmicas
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    make_dataclass decorator: transforme dataclasses

    Aprenda a usar o parâmetro decorator de make_dataclass para validar, registrar e transformar dataclasses dinâmicas no Python.

    Ler mais

    Tempo de leitura: 6 minutos
    23/10/2026
    Estrutura de código e XML para canonicalização com Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    ElementTree canonicalize: normalize XML no Python

    Aprenda ElementTree canonicalize no Python para comparar XML, gerar hashes estáveis e controlar namespaces, espaços e comentários.

    Ler mais

    Tempo de leitura: 5 minutos
    22/10/2026
    Código de programação Python em uma tela
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    T-strings e templatelib: interpolação estruturada

    Aprenda t-strings e string.templatelib no Python para processar interpolações, criar renderizadores seguros e preservar dados estruturados.

    Ler mais

    Tempo de leitura: 6 minutos
    22/10/2026
    Banco SQLite e código Python para exportação seletiva com iterdump
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    SQLite iterdump: crie dumps seletivos no Python

    Aprenda sqlite3.Connection.iterdump com filtro para gerar dumps seletivos, validar dependências e restaurar bancos com segurança.

    Ler mais

    Tempo de leitura: 5 minutos
    21/10/2026