Pular para o conteúdo

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.

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.

▶ Experimente você mesmo

Você também pode começar com um vetor vazio e ir enchendo:

let mut numbers: Vec<i32> = Vec::new();

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]
▶ Experimente você mesmo

A sintaxe com colchetes é a mesma dos arrays:

fn main() {
let fruits = vec!["maçã", "banana", "cereja"];
println!("{}", fruits[0]);
println!("Tamanho: {}", fruits.len());
}
▶ Experimente você mesmo

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"),
}
}
▶ Experimente você mesmo
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);
}
▶ Experimente você mesmo
fn main() {
let numbers = vec![10, 20, 30];
for n in &numbers {
println!("{n}");
}
}
▶ Experimente você mesmo

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.

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”.

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 pares
▶ Experimente você mesmo

Repare que nunca escrevemos o tipo. O Rust vê as chamadas de push(n) e deduz que evens é um Vec<i32>.

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"]
▶ Experimente você mesmo

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 com vec![...] ou Vec::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 um Option e não dá panic.
  • Percorra com for item in &vec para pegar os itens emprestados sem consumir o vetor.

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