Tipos colección

Rust tiene muchos tipos para construir una colección. La colecciones sirven para almacenar más de un valor en un mismo lugar. Por ejemplo, permiten almacenar la información sobre todas las ciudades de un país en una variable.

Se iniciará con los arrays, que son los más rápidos, pero también los que tienen la funcionalidad más limitada. En este sentido, son como el tipo &str.

Arrays

Son los datos guardados dentro de corchetes: [].

Los Arrays:

  • No pueden cambiar de tamaño.
  • Tienen datos del mismo tipo.

Sin embargo, son muy rápidos.

El tipo de un array es: [tipo; longitud]. Por ejemplo, el tipo de ["Uno", "Dos"] es [&str; 2]. Esto significa que los siguientes dos arrays tienen tipos diferentes:

fn main() {
    let array1 = ["One", "Two"]; // Este es de tipo [&str; 2]
    let array2 = ["One", "Two", "Five"]; // Y este de tipo [&str; 3]. ¡Son dos tipos diferentes!
}

Para conocer el tipo de una variable se puede "pedir" al compilador que haga algo con ella que no sea válido, por ejemplo:

fn main() {
    let seasons = ["Spring", "Summer", "Autumn", "Winter"];
    let seasons2 = ["Spring", "Summer", "Fall", "Autumn", "Winter"];
    seasons.ddd(); // ⚠️
    seasons2.thd(); // ⚠️ también
}

El compilador dice, "¿Qué haces? No existe el método .ddd() para la variable seasons y tampoco existe el método .thd() para seasons2" como puedes ver:

error[E0599]: no method named `ddd` found for array `[&str; 4]` in the current scope
 --> src\main.rs:4:13
  |
4 |     seasons.ddd(); // 
  |             ^^^ method not found in `[&str; 4]`

error[E0599]: no method named `thd` found for array `[&str; 5]` in the current scope
 --> src\main.rs:5:14
  |
5 |     seasons2.thd(); // 
  |              ^^^ method not found in `[&str; 5]`

Y dice que method not found in `[&str; 4]`, que es el tipo del array.

Si se necesita un array con el mismo valor en todos los elementos, se puede declarar de la siguiente forma:

fn main() {
    let my_array = ["a"; 10];
    println!("{:?}", my_array);
}

Que imprime ["a", "a", "a", "a", "a", "a", "a", "a", "a", "a"].

Este método se utiliza mucho para crear buffers. Por ejemplo, let mut buffer = [0;640] crea un array de 640 ceros. Posteriormente, se puede modificar el valor cero por otro dato.

Se pueden indexrar los valores (recuperarlos) con []. El primer valor es [0], el segundo [1] y así sucesivamente.

fn main() {
    let my_numbers = [0, 10, -20];
    println!("{}", my_numbers[1]); // imprime 10
}

Se puede obtener una sección (slice) de un array. Lo primero que se necesita es una referencia & porque el compilador no conoce el tamaño. Después se puede usar .. para mostrar el rango.

Por ejemplo, si se utiliza el siguiente array: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].

fn main() {
    let array_of_ten = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

    let three_to_five = &array_of_ten[2..5];
    let start_at_two = &array_of_ten[1..];
    let end_at_five = &array_of_ten[..5];
    let everything = &array_of_ten[..];

    println!("Tres a cinco: {:?}, comienza en el segundo: {:?}, finaliza en el quinto: {:?}, todo: {:?}", three_to_five, start_at_two, end_at_five, everything);
}

Se debe recordar que:

  • Los números de índice comienzan en 0 (no en 1).
  • los rangos son excluyentes (es decir, no incluyen el último número).

Así, [0..2] obtiene el primer y segundo valor (0 y 1). Dicho de otro modo, el índice cero y uno. No obtiene el tercer valor, cuyo índice es dos.

Es posible establecer un rango inclusivo, que sí incluya el último número del rango. Para ello se escribe ..=, en lugar de ... Así que [0..=2] permite obtener el primer, segundo y tercer elemento del array.