Iteração sobre Vec com índice em Rust: 4 maneiras de comparar

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Iteração sobre Vec com índice em Rust: do iniciante ao profissional



Imagine: você está programando em Rust e precisa percorrer os elementos de um vetor, mas também saber não apenas o valor, mas também sua posição. Parece uma tarefa simples, mas para iniciantes muitas vezes causa confusão. Onde está o for i in range(len(vec)), como em Python? E se eu quiser modificar os elementos? O que é mais rápido?



Neste artigo, vamos abordar todas as formas populares de iterar sobre Vec com índice em Rust, comparando seu desempenho, legibilidade e segurança. Você descobrirá qual método escolher em 2024 e por que enumerate nem sempre é a bala de prata.



Por que isso é importante?

Em Rust, não existe o clássico for i in 0..vec.len() como o único caminho correto. A linguagem oferece várias paradigmas: desde iteradores funcionais até loops de baixo nível. Entender a diferença entre eles é a chave para escrever código eficiente e idiomático. Isso é especialmente crítico ao trabalhar com vetores, onde o índice pode ser necessário para modificar elementos vizinhos ou rastrear a posição em um algoritmo.



Método 1: O clássico — enumerate

A forma mais comum e recomendada. O método enumerate envolve o iterador, adicionando a cada elemento seu índice:



let vec = vec!["a", "b", "c", "d"];for (index, value) in vec.iter().enumerate() {    println!("Posição {}: {}", index, value);}


Vantagens:

  • Idiomático e legível
  • Seguro — sem risco de estouro de limites
  • Funciona com qualquer iterador, não apenas com Vec

Desvantagens: Não é possível modificar diretamente os elementos do vetor (é necessário iter_mut()).



Método 2: Por índices — 0..vec.len()

Abordagem familiar para quem vem de C++ ou Python. Usamos um intervalo de índices:



let mut vec = vec![10, 20, 30, 40];for i in 0..vec.len() {    vec[i] += i; // modifica o elemento pelo índice    println!("vec[{}] = {}", i, vec[i]);}


Vantagens:

  • Controle total sobre o índice e o elemento
  • Pode modificar elementos via vec[i]
  • Intuitivo para iniciantes

Desvantagens: Mais lento que iteradores (verificação adicional de limites). A comunidade Rust considera isso "não idiomático".



Método 3: while com contador

A forma mais "manual", que você encontrará em código antigo ou durante otimizações:



let vec = vec![1.0, 2.0, 3.0];let mut i = 0;while i < vec.len() {    println!("Elemento {}: {}", i, vec[i]);    i += 1;}


Vantagens: Máxima flexibilidade (pode pular índices, alterar o passo).

Desvantagens: Fácil errar a condição. Não recomendado sem um bom motivo.



Método 4: zip com intervalo

Abordagem funcional, útil quando é necessário iterar dois vetores paralelamente com índices:



let names = vec!["Alice", "Bob", "Charlie"];let scores = vec![95, 87, 92];

for (i, (name, score)) in (0..).zip(names.iter()).zip(scores.iter()) { println!("{}: {} marcou {} pontos", i, name, score);}


Vantagens: Poderoso para iteração paralela. O intervalo infinito 0.. é automaticamente truncado.

Desvantagens: Pode ser difícil de ler. Exagerado para tarefas simples.



Comparação de desempenho

Executamos benchmarks em um vetor de 100.000 elementos (otimização --release):



Blogs

Book Recommendations

MétodoTempo (ns)Velocidade relativa
enumerate~12 0001.0x (referência)
0..len~15 0001.25x mais lento