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
| Adaptador | O 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
- Filtrar Vetor em Rust — filtragem detalhada com filter(), retain() e partition()
- Ordenar Vetor em Rust — combine iteradores com ordenação
- Usar HashMap em Rust — iteração sobre mapas chave-valor
- Traits e Generics — como o trait Iterator funciona por dentro
- Rust Cheatsheet — referência rápida de todos os adaptadores de iterador
- Glossário Rust: Iterator — definição e exemplo de implementação de Iterator customizado
- Iteradores em Go — compare com a abordagem de iteração em Go