Médio Rust

Contagem de frequência com entry API

Enunciado

Dada a frase "a b a c b a", conte quantas vezes cada palavra aparece usando um HashMap e a entry API. Imprima cada palavra e sua contagem em ordem alfabética.

Requisitos

  • Separar a frase com split_whitespace().
  • Usar entry(...).or_insert(0) para contar.
  • Coletar os pares em um Vec e ordenar por chave antes de imprimir.

Código inicial

use std::collections::HashMap;

fn main() {
    let frase = "a b a c b a";
    // TODO: conte as palavras e imprima em ordem alfabética
}

Saída esperada

a: 3
b: 2
c: 1
Ver dica

Para ordenar, colete contagem.iter() em um Vec de tuplas e use .sort_by_key(|(k, _)| *k).

Mostrar solução
use std::collections::HashMap;

fn main() {
    let frase = "a b a c b a";

    // HashMap que associa &str a u32
    let mut contagem: HashMap<&str, u32> = HashMap::new();

    // Itera pelas palavras separadas por espaços
    for palavra in frase.split_whitespace() {
        // entry: se não existir, insere 0; depois incrementa
        *contagem.entry(palavra).or_insert(0) += 1;
    }

    // Coleta em Vec para poder ordenar (HashMap não tem ordem)
    let mut pares: Vec<(&str, u32)> = contagem.into_iter().collect();
    pares.sort_by_key(|(palavra, _)| *palavra);

    for (palavra, qtd) in &pares {
        println!("{}: {}", palavra, qtd);
    }
}

Passo a passo

  1. let mut contagem: HashMap<&str, u32> = HashMap::new(); cria o mapa com chaves &str (fatias da frase) e valores u32.
  2. frase.split_whitespace() gera um iterador de palavras, ignorando espaços múltiplos.
  3. contagem.entry(palavra).or_insert(0) busca a chave; se não existir, insere 0 e devolve &mut u32 para o valor.
  4. *... += 1 desreferencia a referência mutável e incrementa a contagem. Isso evita duas buscas no mapa.
  5. contagem.into_iter().collect() consome o mapa e cria um Vec de tuplas (&str, u32). Agora podemos ordenar.
  6. pares.sort_by_key(|(palavra, _)| *palavra) ordena alfabeticamente pela chave.
  7. O for final imprime cada par no formato pedido.

Por que funciona

A entry API resolve o padrão "inserir se ausente, depois atualizar" em uma única chamada, sem precisar de get seguido de insert. Como o HashMap não mantém ordem, coletamos em Vec e ordenamos — uma combinação muito comum em Rust.

Erros comuns

  • Tentar contagem[palavra] += 1 sem a chave existir: causa panic em tempo de execução (índice inexistente).
  • Usar contagem.get(palavra) e depois insert: compila, mas faz duas buscas e pode dar erro de empréstimo se misturar referências.
  • Iterar diretamente sobre contagem sem coletar e esperar ordem alfabética: a ordem é arbitrária e o teste falha.

Outra forma de resolver

Se não precisar de ordenação, basta iterar o mapa:

for (palavra, qtd) in &contagem {
    println!("{}: {}", palavra, qtd);
}

É mais curto, mas a ordem de saída não é garantida.

Saída esperada

a: 3
b: 2
c: 1