Trilha de aprendizado · Nível 3 · Tutorial 10

Transformar e filtrar dados com compreensões

Construir listas, dicionários e conjuntos com compreensões legíveis, escolhendo laços explícitos quando a transformação exigir lógica mais extensa.

  • Nível: Iniciante
  • Duração: 22 min
  • 7 passos
Transformar e filtrar dados com compreensões

O que você vai percorrer

  1. Do laço à compreensão de lista Converta um laço com for e append em uma compreensão e preveja a lista produzida. 3 min
  2. Filtrar antes de transformar Combine transformação e filtro em uma compreensão de lista e acompanhe a ordem em que cada parte é avaliada. 4 min
  3. Construir dicionários e lidar com chaves repetidas Calcule chaves e valores em uma compreensão e identifique qual valor permanece quando uma chave se repete. 3 min
  4. Produzir resultados únicos com conjuntos Combine transformação e filtro para obter categorias únicas e confira o resultado sem depender da ordem. 3 min
  5. Novo contêiner não significa cópia profunda Preveja quando uma alteração feita no resultado de uma compreensão também afeta os registros de origem. 3 min
  6. Escolher pela clareza, não pelo tamanho Escolha entre compreensão e laço explícito considerando a intenção, a legibilidade e as ações necessárias. 3 min
  7. Aplicação final: transformar um pequeno catálogo Transforme um catálogo com três compreensões e confira filtros, repetições e chaves repetidas. 5 min

O que você vai aprender

  • Converter um laço simples de construção de lista em uma compreensão.
  • Filtrar elementos com a cláusula if de uma compreensão.
  • Gerar dicionários calculando chaves e valores a partir dos dados de origem.
  • Gerar conjuntos de resultados únicos com compreensões.
  • Avaliar se uma compreensão melhora a leitura e reconhecer que ela não faz uma cópia profunda dos elementos.

Antes de começar

  • Consultar e atualizar dados com dicionários
  • Eliminar duplicatas e comparar grupos com conjuntos
  • Controlar referências e cópias de coleções

Passo 1 de 7

Do laço à compreensão de lista

Converta um laço com for e append em uma compreensão e preveja a lista produzida.

A mesma lista, outra forma de construir

Você já construiu listas com for e append. Uma compreensão de lista é uma expressão que constrói uma nova lista a partir dos dados de origem.

A estrutura é [expressão_de_saída for elemento in origem]. O valor que iria para o append passa a aparecer no início, dentro dos colchetes.

Duas construções equivalentes

python
numeros = [3, 1, 3]

# Com laço e append
dobros = []
for numero in numeros:
    dobros.append(numero * 2)

# Com compreensão de lista
dobros = [numero * 2 for numero in numeros]

print(dobros)  # [6, 2, 6]

Do append para a expressão de saída

Comparação entre dobros.append(numero * 2) dentro de um for e a compreensão [numero * 2 for numero in numeros]. Uma seta liga numero * 2 nas duas formas, e outra liga as cláusulas for.

A expressão de saída aparece primeiro na escrita, mas é calculada para cada elemento percorrido pelo for.

Complete a conversão

Laço de origem

python
numeros = [2, 0, 2]
resultado = []
for numero in numeros:
    resultado.append(numero + 5)

Complete somente a expressão que falta para produzir a mesma lista:

resultado = [___ for numero in numeros]

Transformar textos também

A expressão de saída também pode usar métodos de texto conhecidos. Leia o exemplo assim: “para cada nome em nomes, produza nome.strip().lower()”.

A lista mantém a ordem do percurso e os resultados repetidos. Transformar dois textos no mesmo resultado não elimina nenhum deles.

Um resultado para cada nome

strip remove os espaços das extremidades; lower transforma o texto em minúsculas.

python
nomes = [" Ana ", "BIA", "ana"]
normalizados = [nome.strip().lower() for nome in nomes]

print(normalizados)
# ['ana', 'bia', 'ana']

Preveja a lista

Antes de executar, acompanhe a transformação de cada elemento.

python
palavras = [" SOL ", "lua", "Sol"]
resultado = [palavra.strip().lower() for palavra in palavras]
print(resultado)

Qual lista será exibida?

Passo 2 de 7

Filtrar antes de transformar

Combine transformação e filtro em uma compreensão de lista e acompanhe a ordem em que cada parte é avaliada.

O if seleciona quem entra

Para transformar apenas alguns elementos, acrescente if condição depois da cláusula for.

A fonte é avaliada primeiro. Depois, para cada elemento, Python testa o filtro: só quando a condição é verdadeira ele calcula a expressão de saída e acrescenta o resultado à lista. Embora a expressão de saída apareça à esquerda, ela é calculada depois do teste.

Dobrar apenas os positivos

python
numeros = [-2, 0, 3, 3]
dobros = [numero * 2 for numero in numeros if numero > 0]
print(dobros)
# [6, 6]
A fonte contém -2, 0, 3 e 3. O filtro numero > 0 exclui -2 e 0. Cada ocorrência de 3 passa pelo filtro, é multiplicada por 2 e produz um 6. A lista final é [6, 6].

Fonte → filtro de cada elemento → transformação dos aprovados → lista.

Reconstrua a ordem de avaliação

Ordene o fluxo da compreensão anterior, do início até a inclusão de um elemento aprovado.

  1. Se aprovado, calcular numero * 2.
  2. Avaliar a fonte numeros.
  3. Obter um elemento do percurso e associá-lo a numero.
  4. Testar numero > 0.
  5. Acrescentar o valor calculado à lista de saída.

Excluir não é substituir

Um elemento reprovado não gera um valor substituto: nem 0, nem None. Ele simplesmente não contribui para a lista.

Isso também significa que a expressão de saída não é calculada para ele. No exemplo abaixo, o filtro impede que a divisão seja feita quando numero vale zero.

Só os aprovados geram cálculos

python
numeros = [0, 2, 5]
resultados = [10 / numero for numero in numeros if numero != 0]
print(resultados)
# [5.0, 2.0]

maiores = [10 / numero for numero in numeros if numero > 10]
print(maiores)
# []

Dica

E quando ninguém passa?

A compreensão ainda cria uma lista, mas ela fica vazia: []. No segundo caso, nenhum elemento é maior que 10, então nenhuma divisão é calculada.

Preveja os resultados

Leia sem executar primeiro.

python
numeros = [-3, 0, 2, 2, 7]
triplos = [numero * 3 for numero in numeros if numero >= 2]
print(triplos)

Qual lista será impressa? Explique por que -3 e 0 não geram valores. Depois, preveja o resultado se apenas o filtro mudar para numero > 10.

Escreva pelo menos 30 caracteres (0/30).

Passo 3 de 7

Construir dicionários e lidar com chaves repetidas

Calcule chaves e valores em uma compreensão e identifique qual valor permanece quando uma chave se repete.

Uma expressão para a chave, outra para o valor

Para construir um dicionário, use chaves externas e separe as expressões de chave e valor com dois-pontos:

{expressão_chave: expressão_valor for elemento in origem if condição}

No exemplo abaixo, cada par fornece nome e quantidade. Se a quantidade for positiva, calculamos a chave com o nome normalizado e o valor com o dobro da quantidade. O filtro é opcional.

De pares para um mapeamento

Cada par aprovado gera uma associação entre uma chave e um valor.

python
materiais = [(" Papel ", 4), (" Cola ", 0), (" TINTA ", 3)]

quantidades_dobradas = {
    nome.strip().lower(): quantidade * 2
    for nome, quantidade in materiais
    if quantidade > 0
}

print(quantidades_dobradas)
# {'papel': 8, 'tinta': 6}

Complete a chave e o valor

Expressão da chave

Complete a compreensão para que nomes como " Papel " gerem a chave "papel":

{___: quantidade * 2 for nome, quantidade in materiais if quantidade > 0}

Expressão do valor

Agora complete o valor para guardar o dobro de cada quantidade aprovada:

{nome.strip().lower(): ___ for nome, quantidade in materiais if quantidade > 0}

Entradas diferentes, mesma chave

" Caneta " e "caneta" viram a mesma chave após a normalização. Quando isso acontece, permanece o valor do último par produzido para essa chave, na ordem do percurso. Os valores não são somados.

Uma entrada rejeitada pelo filtro não produz um par e, portanto, não substitui nenhum valor.

A última entrada aprovada prevalece

python
materiais = [
    (" Caneta ", 3),
    ("LÁPIS", 2),
    ("caneta", 5),
    ("CANETA", 0)
]

quantidades_dobradas = {
    nome.strip().lower(): quantidade * 2
    for nome, quantidade in materiais
    if quantidade > 0
}

print(quantidades_dobradas)
# {'caneta': 10, 'lápis': 4}

Acompanhe a chave caneta

Fluxo das entradas de caneta: a quantidade 3 passa pelo filtro e gera caneta: 6; a quantidade 5 passa e substitui o valor por 10; a quantidade 0 é bloqueada pelo filtro. O valor final é 10.

O último elemento da origem é rejeitado. Para caneta, o último valor realmente produzido é 10.

Qual valor fica agora?

Observe a ordem dos pares

Preveja o resultado antes de executar.

python
materiais = [("caneta", 5), (" Caneta ", 3), ("CANETA", 0)]

resultado = {
    nome.strip().lower(): quantidade * 2
    for nome, quantidade in materiais
    if quantidade > 0
}

print(resultado)

Qual dicionário será exibido?

Passo 4 de 7

Produzir resultados únicos com conjuntos

Combine transformação e filtro para obter categorias únicas e confira o resultado sem depender da ordem.

Mesma transformação, outra coleção

Chaves, mas sem chave:valor

A compreensão de conjunto usa a estrutura {expressão for elemento in origem if condição}. Diferentemente do dicionário, há apenas uma expressão de saída, sem o par chave:valor.

No exemplo, a lista e o conjunto usam a mesma transformação e o mesmo filtro. A diferença está nos delimitadores: [] ou {}.

Normalizar e eliminar categorias vazias

python
categorias = [" Livro ", "livro", " PAPEL ", "   "]

lista = [texto.strip().lower() for texto in categorias if texto.strip()]
unicas = {texto.strip().lower() for texto in categorias if texto.strip()}

print(lista)   # ['livro', 'livro', 'papel']
print(unicas)  # Uma exibição possível: {'livro', 'papel'}

A unicidade vale para os resultados

Fluxo das entradas ' Livro ', 'livro', ' PAPEL ' e um texto só com espaços. O texto vazio após strip é excluído. A normalização produz livro, livro e papel. A lista mantém os três resultados; o conjunto contém apenas livro e papel, sem posições.

Entradas diferentes podem produzir o mesmo texto normalizado. A lista mantém a repetição; o conjunto reúne apenas os resultados únicos.

Dica

Confira os elementos, não a ordem

O filtro if texto.strip() exclui textos que ficam vazios após a remoção dos espaços. Para conferir o conjunto, use unicas == {'livro', 'papel'}: o resultado é True, independentemente da ordem de exibição.

O que cada expressão produz?

Associe expressão e resultado

Considere entradas = [' A ', 'a', ' ']. Associe cada compreensão ao resultado. Nos conjuntos, a ordem apresentada não importa.

Toque em um item e depois no par correspondente.

Construa um conjunto de categorias

Dados de origem

Use estes dados para responder. Se quiser executar sua solução, use o Python no seu computador.

python
categorias = [" Arte ", "arte", " CIÊNCIA ", "   ", "ciência", "Música"]

Normalize, filtre e preveja

Escreva uma compreensão que atribua a unicas as categorias sem espaços nas extremidades e em letras minúsculas, excluindo textos que ficam vazios após strip().

Em seguida, indique quais elementos estarão no conjunto. Não é necessário colocá-los em uma ordem específica.

Escreva pelo menos 20 caracteres (0/20).

Passo 5 de 7

Novo contêiner não significa cópia profunda

Preveja quando uma alteração feita no resultado de uma compreensão também afeta os registros de origem.

Lista nova, registro compartilhado

Como você já viu ao estudar referências, um contêiner novo pode compartilhar objetos internos. Na compreensão abaixo, a expressão de saída é registro: ela devolve o próprio dicionário, sem copiá-lo.

python
origem = [
    {"nome": "Caneta", "quantidade": 3},
    {"nome": "Caderno", "quantidade": 0}
]
disponiveis = [registro for registro in origem
               if registro["quantidade"] > 0]

print(disponiveis is origem)        # False
print(disponiveis[0] is origem[0])   # True
Duas listas distintas, origem e disponíveis, apontam para o mesmo dicionário da Caneta. Apenas origem também aponta para o dicionário do Caderno.

O filtro seleciona o registro; não cria uma cópia profunda dele.

Alterar por qual caminho?

Observe este exemplo independente

python
origem = [{"nome": "Caneta", "quantidade": 3}]
disponiveis = [registro for registro in origem
               if registro["quantidade"] > 0]

disponiveis[0]["quantidade"] = 8

Depois desse código, origem[0]["quantidade"] continua sendo 3, porque a compreensão criou uma lista nova.

A expressão de saída faz diferença

Selecionar registro mantém o dicionário compartilhado. Extrair registro["nome"] ou registro["quantidade"] produz uma lista de textos ou números, sem um vínculo que atualize os campos de origem.

Além disso, substituir uma posição da lista resultante muda apenas essa lista: não modifica o objeto que ocupava a posição.

Substituições na lista externa

python
origem = [{"nome": "Caneta", "quantidade": 3}]
selecionados = [registro for registro in origem]
nomes = [registro["nome"] for registro in origem]

# Substitui a referência em uma posição da nova lista.
selecionados[0] = {"nome": "Caderno", "quantidade": 5}

# Substitui um texto na outra lista.
nomes[0] = "Lápis"

print(origem)
# [{'nome': 'Caneta', 'quantidade': 3}]

Dica

Pergunta-chave

Qual objeto está sendo alterado: a nova lista ou um dicionário compartilhado dentro dela? Textos e números são imutáveis; substituí-los na lista não altera o registro de onde foram extraídos.

Preveja o resultado

Leia as duas atribuições na ordem em que acontecem.

python
origem = [{"nome": "Caneta", "quantidade": 3}]
selecionados = [registro for registro in origem]
quantidades = [registro["quantidade"] for registro in origem]

selecionados[0]["quantidade"] = 8
selecionados[0] = {"nome": "Caderno", "quantidade": 0}

print(origem[0]["quantidade"])
print(quantidades)

O que os dois prints exibem? Explique por que substituir selecionados[0] não desfaz a primeira alteração e por que quantidades mantém seu valor.

Escreva pelo menos 20 caracteres (0/20).

Passo 6 de 7

Escolher pela clareza, não pelo tamanho

Escolha entre compreensão e laço explícito considerando a intenção, a legibilidade e as ações necessárias.

Uma transformação fácil de reconhecer

Uma compreensão funciona bem quando a intenção é construir uma coleção com uma transformação clara e um filtro simples. Compare as duas soluções equivalentes: os nomes ajudam a identificar a origem, o filtro e a saída.

Mesmo resultado, duas formas

python
precos = [10, 0, 20]

# Com laço
precos_com_desconto = []
for preco in precos:
    if preco > 0:
        precos_com_desconto.append(preco * 0.9)

# Com compreensão
precos_com_desconto = [preco * 0.9 for preco in precos if preco > 0]

print(precos_com_desconto)  # [9.0, 18.0]

Três partes para localizar

A compreensão destaca a saída preco * 0.9, a origem for preco in precos e o filtro if preco > 0, cada um com uma cor.

Se origem, filtro e saída ficam fáceis de localizar, a compreensão comunica bem a intenção.

Menor não basta

Por que a compreensão do exemplo anterior é uma boa escolha?

Quando o objetivo é executar ações

Prefira o laço quando cada elemento exigir várias ações, alterações nos dados existentes ou lógica extensa. Aqui, a intenção não é produzir uma nova coleção: é atualizar cada pedido pendente e informar a mudança.

Ações separadas e explícitas

python
pedidos = [
    {"numero": 1, "status": "pendente"},
    {"numero": 2, "status": "enviado"}
]

for pedido in pedidos:
    if pedido["status"] == "pendente":
        pedido["status"] = "enviado"
        print("Pedido enviado:", pedido["numero"])

Atenção

Não crie uma lista só para descartá-la

Evite usar [print(pedido["numero"]) for pedido in pedidos] apenas para imprimir. Além das impressões, isso constrói uma lista de None, pois print retorna None. O mesmo problema aparece ao usar uma compreensão apenas para chamar update nos registros. Para essas ações, use um laço.

Escolha e justifique

Escolha compreensão ou laço para cada tarefa e justifique:

A. Criar uma lista com os nomes em letras maiúsculas dos usuários ativos.

B. Percorrer os usuários ativos, mudar o campo ativo para False e imprimir uma confirmação para cada usuário alterado.

Considere o resultado desejado e a quantidade de ações por elemento.

Escreva pelo menos 40 caracteres (0/40).

Passo 7 de 7

Aplicação final: transformar um pequeno catálogo

Transforme um catálogo com três compreensões e confira filtros, repetições e chaves repetidas.

Seu desafio: três resultados do mesmo catálogo

Transforme apenas os materiais disponíveis

No Python do seu computador, crie um script com o código abaixo. Substitua as três coleções vazias por compreensões.

Use quantidade > 0 como filtro nas três:

  • nomes: lista dos nomes normalizados, mantendo a ordem e as repetições.
  • estoque: dicionário que associa cada nome normalizado à sua quantidade.
  • categorias: conjunto das categorias normalizadas dos materiais disponíveis.

Normalize nomes e categorias com strip().lower(). Antes de executar, preveja o que acontecerá com as duas entradas de lápis.

Código inicial completo

As coleções vazias são pontos de partida, não os resultados esperados. Mantenha os dados e os comandos print.

python
catalogo = [
    {"nome": " Lápis ", "categoria": " Papelaria ", "quantidade": 5},
    {"nome": "COLA", "categoria": "Adesivos", "quantidade": 0},
    {"nome": "lápis", "categoria": "papelaria", "quantidade": 2},
    {"nome": " Régua ", "categoria": " MEDIÇÃO ", "quantidade": 3},
]

# Substitua cada coleção vazia por uma compreensão.
nomes = []
estoque = {}
categorias = set()

print(nomes)
print(estoque)
print(categorias)

Escolha a estrutura pela intenção

Um catálogo se ramifica em três estruturas: uma lista com elementos repetidos em sequência, um dicionário com associações entre chaves e valores e um conjunto com símbolos únicos.

Lista: sequência de resultados. Dicionário: associação por chave. Conjunto: resultados únicos.

Execute e explique suas escolhas

O que seu programa produziu?

Execute seu script e registre:

  1. As três compreensões que você escreveu e os resultados observados.
  2. Por que 'lápis' aparece duas vezes na lista, mas tem apenas um valor no dicionário. Qual quantidade permanece?
  3. Imagine uma extensão que, para cada material disponível, imprima um aviso e altere sua quantidade. Você escolheria uma compreensão ou um laço explícito? Justifique.

Não é necessário enviar um arquivo. Na próxima tela, compare seu código com uma solução comentada.

Escreva pelo menos 80 caracteres (0/80).

Compare com a solução

Mesmo filtro, saídas diferentes

As três compreensões selecionam os mesmos registros. O que muda é a expressão de saída e a estrutura construída. No seu script, substitua o trecho que começa em nomes pelo código abaixo, mantendo a definição de catalogo.

Solução comentada

python
# Lista: mantém a ordem e os nomes repetidos.
nomes = [
    material["nome"].strip().lower()
    for material in catalogo
    if material["quantidade"] > 0
]

# Dicionário: o último valor produzido para uma chave prevalece.
estoque = {
    material["nome"].strip().lower(): material["quantidade"]
    for material in catalogo
    if material["quantidade"] > 0
}

# Conjunto: guarda apenas categorias normalizadas únicas.
categorias = {
    material["categoria"].strip().lower()
    for material in catalogo
    if material["quantidade"] > 0
}

print(nomes)
print(estoque)
print(categorias)

Exemplo

Resultados esperados

Lista:
['lápis', 'lápis', 'régua']

Dicionário:
{'lápis': 2, 'régua': 3}

Conjunto — uma ordem de exibição possível:
{'papelaria', 'medição'}

A cola tem quantidade zero e não contribui para nenhuma saída. As duas grafias de lápis viram a mesma chave: o valor 2 substitui o 5. As duas grafias de papelaria também se tornam iguais, deixando apenas um elemento no conjunto.

Leve estes critérios para o próximo programa

Resumo

Revisão final

Escolha a compreensão pela intenção, não apenas pela economia de linhas.

  • Use lista para uma sequência que preserva a ordem de percurso e permite resultados repetidos.
  • Use dicionário para associar chaves a valores; uma chave repetida fica com o último valor produzido.
  • Use conjunto para resultados únicos após a transformação, sem depender da ordem de exibição.
  • Para cada elemento, o filtro decide se a expressão de saída será calculada.
  • Prefira um laço explícito quando houver várias ações, alterações de estado ou lógica extensa. Não construa uma coleção descartável só para executar ações.
  • A compreensão cria um novo contêiner, não uma cópia profunda. Neste desafio você extraiu textos e números; se a saída fosse o próprio registro, ele continuaria compartilhado com o catálogo.

Tutorial concluído

Parabéns! Você concluiu: Transformar e filtrar dados com compreensões

Você chegou ao fim! Agora tem critérios para construir listas, dicionários e conjuntos com compreensões e reconhecer quando um laço explícito deixa a intenção mais clara.

Baixe o Aplicativo agora para ter acesso a + de 5000 cursos gratuitos, exercícios, certificado e muito conteúdo sem pagar nada!

  • Cursos online 100% gratuitos do início ao fim

    Milhares de cursos online em vídeo, ebooks e áudiobooks.

  • Mais de 60 mil exercícios gratuitos

    Para testar seus conhecimentos no decorrer dos cursos online

  • Certificado Digital gratuito válido em todo o Brasil

    Gerado diretamente na galeria de fotos do seu celular e enviado ao seu e-mail

Aplicativo Cursa na tela de ebook, na tela de curso em vídeo e na tela de exercícios do curso, mais o certificado de conclusão de curso