Como Iterar Coleções em Rust

Domine a iteração em Rust: for loop, iter(), map(), fold(), enumerate(), zip(), chain() e mais. Guia completo com exemplos práticos e código executável.

Os iteradores são o coração da programação funcional em Rust. Eles oferecem uma forma expressiva, segura e eficiente de processar coleções — com zero custo em tempo de execução graças à otimização do compilador. Nesta receita, você vai aprender todas as formas de iterar sobre coleções em Rust.

Dependências

Todos os iteradores fazem parte da biblioteca padrão:

[package]
name = "receita-iterar"
version = "0.1.0"
edition = "2021"

Código Completo

use std::collections::HashMap;

fn main() {
    // =============================================
    // 1. for loop — a forma mais simples
    // =============================================
    let frutas = vec!["maçã", "banana", "cereja"];

    // Iteração por referência (não consome o vetor)
    for fruta in &frutas {
        print!("{} ", fruta);
    }
    println!(); // maçã banana cereja

    // Iteração com modificação
    let mut numeros = vec![1, 2, 3, 4, 5];
    for n in &mut numeros {
        *n *= 2;
    }
    println!("Dobrados: {:?}", numeros); // [2, 4, 6, 8, 10]

    // Iteração consumindo o vetor
    let nomes = vec!["Ana".to_string(), "Bia".to_string()];
    for nome in nomes {
        println!("Olá, {}!", nome);
    }
    // nomes não pode mais ser usado aqui

    // =============================================
    // 2. enumerate() — iteração com índice
    // =============================================
    let linguagens = vec!["Rust", "Go", "Zig", "Python"];

    for (i, lang) in linguagens.iter().enumerate() {
        println!("{}. {}", i + 1, lang);
    }

    // =============================================
    // 3. map() — transformar cada elemento
    // =============================================
    let numeros = vec![1, 2, 3, 4, 5];

    let quadrados: Vec<i32> = numeros.iter().map(|&x| x * x).collect();
    println!("\nQuadrados: {:?}", quadrados);
    // [1, 4, 9, 16, 25]

    let nomes = vec!["ana", "bia", "carlos"];
    let capitalizados: Vec<String> = nomes
        .iter()
        .map(|nome| {
            let mut chars = nome.chars();
            match chars.next() {
                None => String::new(),
                Some(c) => c.to_uppercase().to_string() + chars.as_str(),
            }
        })
        .collect();
    println!("Capitalizados: {:?}", capitalizados);

    // =============================================
    // 4. fold() — acumular um resultado
    // =============================================
    let numeros = vec![1, 2, 3, 4, 5];

    // Soma com fold
    let soma = numeros.iter().fold(0, |acc, &x| acc + x);
    println!("\nSoma: {}", soma); // 15

    // Produto com fold
    let produto = numeros.iter().fold(1, |acc, &x| acc * x);
    println!("Produto: {}", produto); // 120

    // Construir string com fold
    let palavras = vec!["Rust", "é", "incrível"];
    let frase = palavras.iter().fold(String::new(), |mut acc, &p| {
        if !acc.is_empty() {
            acc.push(' ');
        }
        acc.push_str(p);
        acc
    });
    println!("Frase: {}", frase); // Rust é incrível

    // reduce() — como fold, mas usa o primeiro elemento como valor inicial
    let max = numeros.iter().copied().reduce(|a, b| if a > b { a } else { b });
    println!("Máximo: {:?}", max); // Some(5)

    // =============================================
    // 5. zip() — combinar dois iteradores
    // =============================================
    let nomes = vec!["Ana", "Bia", "Carlos"];
    let notas = vec![9.5, 8.0, 7.5];

    let boletim: Vec<(&str, f64)> = nomes.iter().copied().zip(notas.iter().copied()).collect();
    println!("\nBoletim: {:?}", boletim);

    // zip para criar HashMap
    let chaves = vec!["host", "porta", "debug"];
    let valores = vec!["localhost", "8080", "true"];
    let config: HashMap<&str, &str> = chaves.into_iter().zip(valores).collect();
    println!("Config: {:?}", config);

    // =============================================
    // 6. chain() — concatenar iteradores
    // =============================================
    let primeira_metade = vec![1, 2, 3];
    let segunda_metade = vec![4, 5, 6];

    let completo: Vec<&i32> = primeira_metade.iter().chain(segunda_metade.iter()).collect();
    println!("\nEncadeado: {:?}", completo); // [1, 2, 3, 4, 5, 6]

    // chain com ranges
    let sequencia: Vec<i32> = (1..=3).chain(10..=12).collect();
    println!("Chain de ranges: {:?}", sequencia); // [1, 2, 3, 10, 11, 12]

    // =============================================
    // 7. flat_map() — map que achata resultados
    // =============================================
    let frases = vec!["olá mundo", "rust é ótimo"];
    let palavras: Vec<&str> = frases.iter().flat_map(|f| f.split_whitespace()).collect();
    println!("\nPalavras: {:?}", palavras);
    // ["olá", "mundo", "rust", "é", "ótimo"]

    // =============================================
    // 8. Consumidores úteis
    // =============================================
    let numeros = vec![3, 7, 2, 9, 1, 5, 8];

    println!("\n--- Consumidores ---");
    println!("sum:     {}", numeros.iter().sum::<i32>());
    println!("product: {}", numeros.iter().product::<i32>());
    println!("min:     {:?}", numeros.iter().min());
    println!("max:     {:?}", numeros.iter().max());
    println!("count:   {}", numeros.iter().count());

    // find — primeiro que satisfaz o predicado
    let primeiro_grande = numeros.iter().find(|&&x| x > 5);
    println!("Primeiro > 5: {:?}", primeiro_grande); // Some(7)

    // position — índice do primeiro que satisfaz
    let pos = numeros.iter().position(|&x| x == 9);
    println!("Posição do 9: {:?}", pos); // Some(3)

    // for_each — executar efeito colateral
    print!("for_each: ");
    numeros.iter().for_each(|x| print!("{} ", x));
    println!();

    // =============================================
    // 9. Iterando sobre HashMap
    // =============================================
    let mut pontuacao: HashMap<&str, i32> = HashMap::new();
    pontuacao.insert("Ana", 100);
    pontuacao.insert("Bia", 85);
    pontuacao.insert("Carlos", 92);

    println!("\n--- Pontuação ---");
    for (nome, pontos) in &pontuacao {
        println!("{}: {} pontos", nome, pontos);
    }

    // Transformar HashMap com iteradores
    let aprovados: Vec<&&str> = pontuacao
        .iter()
        .filter(|(_, &pontos)| pontos >= 90)
        .map(|(nome, _)| nome)
        .collect();
    println!("Aprovados (>=90): {:?}", aprovados);

    // =============================================
    // 10. windows() e chunks() — iteração em fatias
    // =============================================
    let dados = vec![1, 2, 3, 4, 5, 6, 7];

    print!("\nJanelas de 3: ");
    for janela in dados.windows(3) {
        print!("{:?} ", janela);
    }
    println!(); // [1,2,3] [2,3,4] [3,4,5] [4,5,6] [5,6,7]

    print!("Chunks de 3:  ");
    for pedaco in dados.chunks(3) {
        print!("{:?} ", pedaco);
    }
    println!(); // [1,2,3] [4,5,6] [7]
}

Saída do Programa

maçã banana cereja
Dobrados: [2, 4, 6, 8, 10]
Olá, Ana!
Olá, Bia!
1. Rust
2. Go
3. Zig
4. Python

Quadrados: [1, 4, 9, 16, 25]
Capitalizados: ["Ana", "Bia", "Carlos"]

Soma: 15
Produto: 120
Frase: Rust é incrível
Máximo: Some(5)

Boletim: [("Ana", 9.5), ("Bia", 8.0), ("Carlos", 7.5)]
Config: {"host": "localhost", "porta": "8080", "debug": "true"}

Encadeado: [1, 2, 3, 4, 5, 6]
Chain de ranges: [1, 2, 3, 10, 11, 12]

Palavras: ["olá", "mundo", "rust", "é", "ótimo"]

--- Consumidores ---
sum:     35
product: 15120
min:     Some(1)
max:     Some(9)
count:   7
Primeiro > 5: Some(7)
Posição do 9: Some(3)
for_each: 3 7 2 9 1 5 8

--- Pontuação ---
Ana: 100 pontos
Bia: 85 pontos
Carlos: 92 pontos
Aprovados (>=90): ["Ana", "Carlos"]

Janelas de 3: [1, 2, 3] [2, 3, 4] [3, 4, 5] [4, 5, 6] [5, 6, 7]
Chunks de 3:  [1, 2, 3] [4, 5, 6] [7]

Resumo dos Principais Adaptadores

AdaptadorO que faz
map()Transforma cada elemento
filter()Mantém elementos que satisfazem predicado
enumerate()Adiciona índice a cada elemento
zip()Combina dois iteradores em pares
chain()Concatena dois iteradores
flat_map()map + flatten (achata resultados aninhados)
fold()Acumula resultado a partir de valor inicial
take(n)Pega os primeiros n elementos
skip(n)Pula os primeiros n elementos
windows(n)Janela deslizante de tamanho n
chunks(n)Divide em pedaços de tamanho n

Veja Também