Array in Rust
Un array è una lista di valori a dimensione fissa, tutti dello stesso tipo. «Dimensione fissa» è la parola chiave: una volta creato, un array non può crescere né rimpicciolirsi. Se ti serve qualcosa che cambia dimensione, per quello c’è il vettore.
Creare un array
Sezione intitolata “Creare un array”fn main() { let numbers: [i32; 5] = [1, 2, 3, 4, 5]; println!("{:?}", numbers);}Il tipo [i32; 5] si legge «un array di 5 valori i32». La lunghezza fa parte del tipo: [i32; 5] e [i32; 3] sono considerati tipi diversi.
Puoi anche lasciare che Rust deduca il tipo e scrivere solo i valori:
let numbers = [1, 2, 3, 4, 5];Lo stesso valore, ripetuto
Sezione intitolata “Lo stesso valore, ripetuto”Per riempire un array con lo stesso valore N volte, usa questa scorciatoia:
fn main() { let zeros = [0; 5]; // [0, 0, 0, 0, 0] println!("{:?}", zeros);}Leggere gli elementi
Sezione intitolata “Leggere gli elementi”Gli indici di un array partono da 0 e si scrivono tra parentesi quadre:
fn main() { let fruits = ["mela", "banana", "ciliegia"];
println!("{}", fruits[0]); // mela println!("{}", fruits[2]); // ciliegia println!("Lunghezza: {}", fruits.len());}Gli accessi fuori dai limiti vengono intercettati
Sezione intitolata “Gli accessi fuori dai limiti vengono intercettati”Prova a leggere un indice che non esiste: Rust ferma il programma invece di leggere in silenzio memoria spazzatura:
fn get_fruit(fruits: [&str; 3], index: usize) -> &str { fruits[index]}
fn main() { let fruits = ["mela", "banana", "ciliegia"]; println!("{}", get_fruit(fruits, 10)); // va in panic durante l'esecuzione}thread 'main' (12345) panicked at src/main.rs:2:5:index out of bounds: the len is 3 but the index is 10Il messaggio di panic resta in inglese, come lo stampa Rust: dice che l’indice è fuori dai limiti, perché la lunghezza è 3 ma l’indice è 10.
Scorrere un array
Sezione intitolata “Scorrere un array”fn main() { let numbers = [10, 20, 30];
for n in numbers { println!("{n}"); }}Array di array (array 2D)
Sezione intitolata “Array di array (array 2D)”Un array può contenere altri array. Così ottieni una griglia con righe e colonne, come una scacchiera o un piccolo foglio di calcolo. Il tipo di grid qui sotto è [[i32; 3]; 2], che si legge «2 righe, ognuna un array di 3 valori i32».
fn main() { // 2 righe, 3 colonne let grid = [ [1, 2, 3], [4, 5, 6], ];
println!("Riga 1, colonna 2: {}", grid[1][2]);
let mut total = 0; for row in grid { println!("{:?}", row); for value in row { total += value; } } println!("Totale: {total}");}Output:
Riga 1, colonna 2: 6[1, 2, 3][4, 5, 6]Totale: 21grid[1][2] significa «riga 1, poi colonna 2 dentro quella riga». Entrambi gli indici partono da 0, quindi è la seconda riga, terzo valore. Per visitare ogni valore usa un ciclo per le righe e, dentro, un secondo ciclo per i valori di ogni riga.
Tutte le righe devono avere la stessa lunghezza, perché la lunghezza della riga fa parte del tipo. Se mentre scorri ti serve anche la posizione, .iter().enumerate() ti dà indice e valore insieme. Lo trovi nella pagina sul ciclo for.
Array o vettori?
Sezione intitolata “Array o vettori?”Usa un array quando la dimensione è fissa e la conosci in anticipo (come i sette giorni della settimana). Usa un Vec quando devi aggiungere o togliere elementi, cioè, in pratica, quasi sempre. Nel codice Rust di tutti i giorni gli array sono meno comuni dei vettori.
Pratica
Sezione intitolata “Pratica”1. Somma e media
Sezione intitolata “1. Somma e media”Crea l’array [4, 8, 15, 16, 23, 42]. Somma tutti i valori, poi stampa la somma e la media con due cifre decimali. Suggerimento: scorri con for, tieni un total parziale e converti entrambi i numeri in f64 con as prima di dividere.
Mostra la soluzione
fn main() { let numbers = [4, 8, 15, 16, 23, 42];
let mut total = 0; for n in numbers { total += n; }
let average = total as f64 / numbers.len() as f64; println!("Somma: {total}"); println!("Media: {average:.2}");}Output:
Somma: 108Media: 18.00Senza as f64, total / numbers.len() sarebbe una divisione intera, e Rust si lamenterebbe anche che total (un i32) e len() (un usize) sono di tipi diversi.
2. Il giorno più caldo
Sezione intitolata “2. Il giorno più caldo”Hai le temperature di una settimana: [18, 25, 12, 31, 22, 27, 19]. Trova e stampa la più alta. Suggerimento: parti da let mut hottest = temps[0];, poi scorri e sostituiscila ogni volta che trovi un valore più grande.
Mostra la soluzione
fn main() { let temps = [18, 25, 12, 31, 22, 27, 19];
let mut hottest = temps[0]; for t in temps { if t > hottest { hottest = t; } }
println!("Giorno più caldo: {hottest}");}Output:
Giorno più caldo: 31Partire da temps[0] invece che da 0 è importante: se tutte le temperature fossero sotto zero, partire da 0 darebbe una risposta sbagliata.
Riepilogo
Sezione intitolata “Riepilogo”- Gli array hanno una lunghezza fissa che fa parte del loro tipo:
[i32; 5]. - Leggi gli elementi con
array[indice], a partire da 0. - Un accesso fuori dai limiti va in panic durante l’esecuzione invece di causare un comportamento indefinito.
- Gli array possono contenere array:
[[i32; 3]; 2]è una griglia che leggi congrid[riga][colonna]. - Se devi cambiare dimensione, usa invece un
Vec.
Verifica veloce
Sezione intitolata “Verifica veloce”Verifica veloce
1. Che cosa è vero sulla lunghezza di un array in Rust?
2. Che cosa succede se durante l'esecuzione accedi a un indice fuori dai limiti di un array?
3. Che cosa crea let zeros = [0; 5]; ?
Punteggio: 0 / 3
Per approfondire
Sezione intitolata “Per approfondire”- The Array Type — The Rust Book (in inglese): l’introduzione ufficiale agli array, compreso il perché la lunghezza fa parte del tipo.
- Arrays and Slices — Rust by Example (in inglese): brevi esempi eseguibili, più un primo sguardo alle slice.
- Looping Through a Collection with
for— The Rust Book (in inglese): perché un cicloforè più sicuro che percorrere un array con un indice. array— documentazione della libreria standard (in inglese): cosa sanno fare gli array, comemapeas_slice, e come prendono in prestito anche tutti i metodi delle slice.