Vectores en Rust
Un vector (Vec) es como un array, pero puede crecer y encogerse mientras el programa se ejecuta. En el código Rust del día a día, cuando necesitas una lista de cosas, vas a usar un Vec mucho más a menudo que un array de tamaño fijo.
Crear un vector
Sección titulada «Crear un vector»fn main() { let numbers: Vec<i32> = vec![1, 2, 3]; println!("{:?}", numbers);}vec![] es una macro (fíjate en el !) que construye un Vec a partir de una lista de valores, de forma parecida a como escribirías un array.
También puedes empezar con uno vacío e ir llenándolo:
let mut numbers: Vec<i32> = Vec::new();Añadir elementos
Sección titulada «Añadir elementos»Usa .push() para añadir al final. El vector tiene que ser mut, porque lo estás modificando:
fn main() { let mut numbers = Vec::new();
numbers.push(1); numbers.push(2); numbers.push(3);
println!("{:?}", numbers);}Salida:
[1, 2, 3]Acceder a los elementos
Sección titulada «Acceder a los elementos»Con la misma sintaxis de corchetes que los arrays:
fn main() { let fruits = vec!["manzana", "banana", "cereza"];
println!("{}", fruits[0]); println!("Longitud: {}", fruits.len());}Si quieres una búsqueda más segura, que no haga panic con un índice incorrecto, usa .get(), que te devuelve un Option (lo verás con calma en la página de Option):
fn main() { let fruits = vec!["manzana", "banana", "cereza"];
match fruits.get(10) { Some(fruit) => println!("Encontrada: {fruit}"), None => println!("No hay ninguna fruta en ese índice"), }}Quitar elementos
Sección titulada «Quitar elementos»fn main() { let mut numbers = vec![1, 2, 3, 4, 5];
numbers.pop(); // quita el último elemento -> [1, 2, 3, 4] numbers.remove(0); // quita por índice -> [2, 3, 4]
println!("{:?}", numbers);}Recorrer un vector con un bucle
Sección titulada «Recorrer un vector con un bucle»fn main() { let numbers = vec![10, 20, 30];
for n in &numbers { println!("{n}"); }}Fíjate en el & delante de numbers. Recorrer con for n in &numbers toma prestado (borrowing) cada elemento, en lugar de quedarse con el ownership del vector. Si quitas el &, el vector se mueve al bucle y ya no podrás usar numbers después. Casi siempre lo que quieres es tomarlo prestado.
Unas palabras sobre los genéricos
Sección titulada «Unas palabras sobre los genéricos»Habrás notado que el tipo se escribe Vec<i32>. La parte <i32> dice “un vector de valores i32”. Esta notación con corchetes angulares se llama genérico, y la verás a fondo en la página de Genéricos. Por ahora, lee Vec<T> como “un vector que guarda valores de tipo T”.
Práctica
Sección titulada «Práctica»1. Recoge los números pares
Sección titulada «1. Recoge los números pares»Empieza con un vector vacío. Recorre los números del 1 al 10 y añade solo los pares. Después, imprime el vector y cuántos elementos tiene. Pista: un número n es par cuando n % 2 == 0.
Ver solución
fn main() { let mut evens = Vec::new();
for n in 1..=10 { if n % 2 == 0 { evens.push(n); } }
println!("{:?}", evens); println!("Encontré {} números pares", evens.len());}Salida:
[2, 4, 6, 8, 10]Encontré 5 números paresFíjate en que nunca escribimos el tipo. Rust ve las llamadas a push(n) y deduce que evens es un Vec<i32>.
2. Una pila de platos
Sección titulada «2. Una pila de platos»Pon tres platos en un vector: "azul", "verde" y luego "rojo". Saca dos platos de arriba con .pop() e imprime cada uno. Por último, imprime lo que queda. Pista: .pop() devuelve un Option, así que imprímelo con {:?}.
Ver solución
fn main() { let mut plates = Vec::new(); plates.push("azul"); plates.push("verde"); plates.push("rojo");
println!("Saqué {:?}", plates.pop()); println!("Saqué {:?}", plates.pop()); println!("Quedan: {:?}", plates);}Salida:
Saqué Some("rojo")Saqué Some("verde")Quedan: ["azul"]pop() siempre saca el último elemento que añadiste, como quien toma el plato de arriba de una pila. Devuelve Some(...) y no el valor a secas, porque el vector podría estar vacío. En ese caso obtendrías None en lugar de un fallo.
Resumen
Sección titulada «Resumen»Vec<T>es una lista que puede crecer; créala convec![...]oVec::new()..push()añade al final;.pop()quita el último elemento;.remove(i)quita por índice.vec[i]hace panic con un índice incorrecto;.get(i)devuelve unOptiony no hace panic.- Recorre con
for item in &vecpara tomar prestados los elementos en lugar de consumir el vector.
Comprueba lo que aprendiste
Sección titulada «Comprueba lo que aprendiste»Comprueba lo aprendido
1. ¿Qué pasa si accedes a un Vec con un índice incorrecto, como numbers[10]?
2. ¿Qué método te permite consultar un índice sin arriesgarte a un panic?
3. ¿Qué hace el & en for n in &numbers?
Puntuación: 0 / 3
Para leer más
Sección titulada «Para leer más»- Guardar listas de valores con vectores — El libro de Rust (en inglés): cómo crear, leer y modificar vectores, y por qué no puedes hacer
pushmientras tienes una referencia. - Vectores — Rust by Example (en inglés): un ejemplo ejecutable que muestra las operaciones más comunes de
Vec. Vec— documentación de la biblioteca estándar (en inglés): la lista completa de métodos, comoinsert,retain,extendycontains.- La macro
vec!— documentación de la biblioteca estándar (en inglés): todas las formas devec!, incluidavec![0; 10]para valores repetidos.