Fácil Rust

Filtrar e dobrar números ímpares

Enunciado

Dado o vetor numeros = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10], use iteradores para criar um novo vetor contendo apenas os números ímpares multiplicados por 3.

Requisitos

  • Use iter(), filter e map.
  • O resultado deve ser um Vec<i32>.
  • Imprima o vetor resultante.

Código inicial

fn main() {
    let numeros = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    // complete com iteradores
    let resultado: Vec<i32> = numeros
        .iter()
        // ...
        .collect();
    println!("{:?}", resultado);
}

Saída esperada

[3, 9, 15, 21, 27]
Ver dica

Dentro do filter, use |&&x| x % 2 != 0. No map, use |&x| x * 3.

Mostrar solução
fn main() {
    let numeros = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

    // Filtra ímpares e multiplica por 3
    let resultado: Vec<i32> = numeros
        .iter()          // iterador sobre referências
        .filter(|&&x| x % 2 != 0)  // mantém apenas ímpares
        .map(|&x| x * 3)           // transforma cada valor
        .collect();                // coleta em Vec

    println!("{:?}", resultado);
}

Passo a passo

  1. numeros.iter() cria um iterador que produz referências (&i32) aos elementos do vetor.
  2. .filter(|&&x| x % 2 != 0) usa um padrão de desestruturação: o primeiro & é da referência do iterador, o segundo & é da referência do item. A condição mantém apenas números ímpares.
  3. .map(|&x| x * 3) desestrutura a referência e multiplica o valor por 3.
  4. .collect() consome o iterador e coleta os resultados em um Vec<i32>, cujo tipo é anotado na variável.
  5. println! imprime o vetor formatado.

Por que funciona

Os adaptadores filter e map são preguiçosos, mas collect é um consumidor que força a execução. O compilador infere os tipos corretamente porque resultado é anotado como Vec<i32>. A cadeia é eficiente e não cria vetores intermediários.

Erros comuns

  • Esquecer o & no padrão: |x| x % 2 != 0 causaria erro de tipo, pois x seria &&i32. Corrija com |&&x|.
  • Não anotar o tipo de collect: let resultado = ...collect(); pode falhar na inferência. Especifique Vec<i32> ou use turbofish collect::<Vec<i32>>().
  • Usar into_iter sem necessidade: into_iter consumiria o vetor, impedindo uso posterior. Prefira iter para empréstimo.

Outra forma de resolver

Usar filter_map para combinar filtro e mapa em uma passada:

let resultado: Vec<i32> = numeros.iter().filter_map(|&x| if x % 2 != 0 { Some(x * 3) } else { None }).collect();

É preferível quando a transformação pode falhar (retornar Option).

Saída esperada

[3, 9, 15, 21, 27]