Vetores em Rust
Um vetor (Vec) é parecido com um array, mas pode crescer e diminuir enquanto o programa roda. No código Rust do dia a dia, quando você precisa de uma lista de coisas, vai usar um Vec muito mais vezes do que um array de tamanho fixo.
Criando um vetor
Seção intitulada “Criando um vetor”fn main() { let numbers: Vec<i32> = vec![1, 2, 3]; println!("{:?}", numbers);}vec![] é uma macro (repare no !) que monta um Vec a partir de uma lista de valores, do mesmo jeito que você escreveria um array.
Você também pode começar com um vetor vazio e ir enchendo:
let mut numbers: Vec<i32> = Vec::new();Adicionando elementos
Seção intitulada “Adicionando elementos”Use .push() para adicionar no final. O vetor precisa ser mut, porque você vai modificá-lo:
fn main() { let mut numbers = Vec::new();
numbers.push(1); numbers.push(2); numbers.push(3);
println!("{:?}", numbers);}Saída:
[1, 2, 3]Acessando os elementos
Seção intitulada “Acessando os elementos”A sintaxe com colchetes é a mesma dos arrays:
fn main() { let fruits = vec!["maçã", "banana", "cereja"];
println!("{}", fruits[0]); println!("Tamanho: {}", fruits.len());}Para uma busca mais segura, que não dá panic com um índice inválido, use .get(). Ele devolve um Option (falamos mais sobre isso na página de Option):
fn main() { let fruits = vec!["maçã", "banana", "cereja"];
match fruits.get(10) { Some(fruit) => println!("Encontrei: {fruit}"), None => println!("Não há fruta nesse índice"), }}Removendo elementos
Seção intitulada “Removendo elementos”fn main() { let mut numbers = vec![1, 2, 3, 4, 5];
numbers.pop(); // remove o último item -> [1, 2, 3, 4] numbers.remove(0); // remove pelo índice -> [2, 3, 4]
println!("{:?}", numbers);}Percorrendo um vetor
Seção intitulada “Percorrendo um vetor”fn main() { let numbers = vec![10, 20, 30];
for n in &numbers { println!("{n}"); }}Repare no & antes de numbers. Com for n in &numbers, o laço faz borrowing (empréstimo) de cada item em vez de tomar o ownership (posse) do vetor. Se você tirar o &, o vetor é movido para dentro do laço e você não consegue mais usar numbers depois dele. Quase sempre, o que você quer é pegar emprestado.
Uma palavrinha sobre genéricos
Seção intitulada “Uma palavrinha sobre genéricos”Você deve ter notado que o tipo é escrito Vec<i32>. A parte <i32> quer dizer “um vetor de valores i32”. Essa notação com sinais de menor e maior se chama genérico, e você vai vê-la com calma na página de Genéricos. Por enquanto, leia Vec<T> como “um vetor que guarda valores do tipo T”.
Prática
Seção intitulada “Prática”1. Junte os números pares
Seção intitulada “1. Junte os números pares”Comece com um vetor vazio. Percorra os números de 1 a 10 e adicione só os pares. Depois, imprima o vetor e quantos itens ele tem. Dica: um número n é par quando n % 2 == 0.
Ver solução
fn main() { let mut evens = Vec::new();
for n in 1..=10 { if n % 2 == 0 { evens.push(n); } }
println!("{:?}", evens); println!("Encontrei {} números pares", evens.len());}Saída:
[2, 4, 6, 8, 10]Encontrei 5 números paresRepare que nunca escrevemos o tipo. O Rust vê as chamadas de push(n) e deduz que evens é um Vec<i32>.
2. Uma pilha de pratos
Seção intitulada “2. Uma pilha de pratos”Coloque três pratos em um vetor: "azul", "verde" e depois "vermelho". Tire dois pratos do topo com .pop() e imprima cada um. Por fim, imprima o que sobrou. Dica: o .pop() devolve um Option, então imprima com {:?}.
Ver solução
fn main() { let mut plates = Vec::new(); plates.push("azul"); plates.push("verde"); plates.push("vermelho");
println!("Tirei {:?}", plates.pop()); println!("Tirei {:?}", plates.pop()); println!("Sobrou: {:?}", plates);}Saída:
Tirei Some("vermelho")Tirei Some("verde")Sobrou: ["azul"]O pop() sempre tira o último item que você adicionou, como pegar o prato de cima de uma pilha. Ele devolve Some(...), e não o valor puro, porque o vetor pode estar vazio. Nesse caso, você recebe None em vez de o programa travar.
Vec<T>é uma lista que cresce; crie uma comvec![...]ouVec::new()..push()adiciona no final;.pop()remove o último item;.remove(i)remove pelo índice.vec[i]dá panic com um índice inválido;.get(i)devolve umOptione não dá panic.- Percorra com
for item in &vecpara pegar os itens emprestados sem consumir o vetor.
Teste o que aprendeu
Seção intitulada “Teste o que aprendeu”Teste o que aprendeu
1. O que acontece quando você acessa um Vec com um índice inválido, como numbers[10]?
2. Qual método permite buscar um índice sem risco de panic?
3. O que o & faz em for n in &numbers?
Pontuação: 0 / 3
Para saber mais
Seção intitulada “Para saber mais”- Storing Lists of Values with Vectors — The Rust Book (em inglês): como criar, ler e atualizar vetores, e por que você não pode dar
pushenquanto segura uma referência. - Vectors — Rust by Example (em inglês): um exemplo executável que mostra as operações mais comuns de
Vec. Vec— documentação da std (em inglês): a lista completa de métodos, comoinsert,retain,extendecontains.- A macro
vec!— documentação da std (em inglês): todas as formas dovec!, incluindovec![0; 10]para valores repetidos.