Mảng trong Rust
Mảng (array) là một danh sách các giá trị có kích thước cố định, tất cả cùng một kiểu. “Kích thước cố định” là từ khóa quan trọng — một khi đã tạo mảng, nó không thể dài ra hay ngắn lại. Nếu bạn cần thứ gì đó đổi được kích thước, đó là việc của vector.
Tạo một mảng
Phần tiêu đề “Tạo một mảng”fn main() { let numbers: [i32; 5] = [1, 2, 3, 4, 5]; println!("{:?}", numbers);}Kiểu [i32; 5] được đọc là “một mảng gồm 5 giá trị i32.” Độ dài đó là một phần của kiểu — [i32; 5] và [i32; 3] được coi là hai kiểu khác nhau.
Bạn cũng có thể để Rust tự suy ra kiểu và chỉ viết các giá trị:
let numbers = [1, 2, 3, 4, 5];Cùng một giá trị, lặp lại
Phần tiêu đề “Cùng một giá trị, lặp lại”Để lấp đầy mảng bằng cùng một giá trị N lần, hãy dùng cách viết tắt này:
fn main() { let zeros = [0; 5]; // [0, 0, 0, 0, 0] println!("{:?}", zeros);}Truy cập phần tử
Phần tiêu đề “Truy cập phần tử”Mảng được đánh chỉ số từ 0, dùng dấu ngoặc vuông:
fn main() { let fruits = ["táo", "chuối", "anh đào"];
println!("{}", fruits[0]); // táo println!("{}", fruits[2]); // anh đào println!("Độ dài: {}", fruits.len());}Truy cập ngoài giới hạn bị chặn lại
Phần tiêu đề “Truy cập ngoài giới hạn bị chặn lại”Nếu bạn truy cập một chỉ số không tồn tại, Rust sẽ dừng chương trình thay vì âm thầm đọc vùng nhớ rác:
fn get_fruit(fruits: [&str; 3], index: usize) -> &str { fruits[index]}
fn main() { let fruits = ["táo", "chuối", "anh đào"]; println!("{}", get_fruit(fruits, 10)); // panic lúc chạy}thread 'main' (12345) panicked at src/main.rs:2:5:index out of bounds: the len is 3 but the index is 10Thông báo panic này (Rust luôn in bằng tiếng Anh) nói rằng chỉ số nằm ngoài giới hạn: độ dài là 3 nhưng chỉ số là 10.
Duyệt qua một mảng
Phần tiêu đề “Duyệt qua một mảng”fn main() { let numbers = [10, 20, 30];
for n in numbers { println!("{n}"); }}Mảng của mảng (mảng 2 chiều)
Phần tiêu đề “Mảng của mảng (mảng 2 chiều)”Một mảng có thể chứa các mảng khác. Nhờ đó bạn có một lưới gồm hàng và cột, như bàn cờ hay một bảng tính nhỏ. Kiểu của grid dưới đây là [[i32; 3]; 2], đọc là “2 hàng, mỗi hàng là một mảng gồm 3 giá trị i32.”
fn main() { // 2 hàng, 3 cột let grid = [ [1, 2, 3], [4, 5, 6], ];
println!("Hàng 1, cột 2: {}", grid[1][2]);
let mut total = 0; for row in grid { println!("{:?}", row); for value in row { total += value; } } println!("Tổng: {total}");}Kết quả:
Hàng 1, cột 2: 6[1, 2, 3][4, 5, 6]Tổng: 21grid[1][2] nghĩa là “hàng 1, rồi cột 2 bên trong hàng đó.” Cả hai đều đếm từ 0, nên đây là hàng thứ hai, giá trị thứ ba. Để đi qua mọi giá trị, dùng một vòng lặp cho các hàng và một vòng lặp thứ hai bên trong cho các giá trị của mỗi hàng.
Mọi hàng phải có cùng độ dài, vì độ dài hàng là một phần của kiểu. Nếu bạn cần cả vị trí khi duyệt, .iter().enumerate() cho bạn chỉ số và giá trị cùng lúc. Nó được giới thiệu trong bài vòng lặp for.
Mảng so với vector
Phần tiêu đề “Mảng so với vector”Dùng mảng khi kích thước cố định và biết trước (như bảy ngày trong tuần). Dùng Vec khi bạn cần thêm hoặc bớt phần tử — mà trong thực tế, đó là phần lớn trường hợp. Trong code Rust hằng ngày, mảng ít phổ biến hơn vector.
Luyện tập
Phần tiêu đề “Luyện tập”1. Tổng và trung bình
Phần tiêu đề “1. Tổng và trung bình”Tạo mảng [4, 8, 15, 16, 23, 42]. Cộng tất cả các giá trị, rồi in ra tổng và giá trị trung bình với hai chữ số thập phân. Gợi ý: duyệt bằng for, giữ một biến total cộng dồn, và đổi cả hai số sang f64 bằng as trước khi chia.
Xem lời giải
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!("Tổng: {total}"); println!("Trung bình: {average:.2}");}Kết quả:
Tổng: 108Trung bình: 18.00Nếu thiếu as f64, total / numbers.len() sẽ là phép chia nguyên, và Rust còn phàn nàn rằng total (một i32) và len() (một usize) là hai kiểu khác nhau.
2. Ngày nóng nhất
Phần tiêu đề “2. Ngày nóng nhất”Bạn có nhiệt độ của một tuần: [18, 25, 12, 31, 22, 27, 19]. Hãy tìm và in ra nhiệt độ cao nhất. Gợi ý: bắt đầu với let mut hottest = temps[0];, rồi duyệt và thay thế nó mỗi khi gặp giá trị lớn hơn.
Xem lời giải
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!("Ngày nóng nhất: {hottest}");}Kết quả:
Ngày nóng nhất: 31Bắt đầu từ temps[0] thay vì 0 là quan trọng: nếu mọi nhiệt độ đều dưới 0, bắt đầu từ 0 sẽ cho đáp án sai.
Tóm tắt
Phần tiêu đề “Tóm tắt”- Mảng có độ dài cố định, và độ dài là một phần của kiểu:
[i32; 5]. - Truy cập phần tử bằng
array[index], bắt đầu từ 0. - Truy cập ngoài giới hạn sẽ panic lúc chạy thay vì gây ra hành vi không xác định.
- Mảng có thể chứa mảng:
[[i32; 3]; 2]là một lưới mà bạn đọc bằnggrid[row][column]. - Nếu cần đổi kích thước, hãy dùng
Vec.
Kiểm tra nhanh
Phần tiêu đề “Kiểm tra nhanh”Kiểm tra nhanh
1. Điều gì đúng về độ dài của mảng trong Rust?
2. Điều gì xảy ra khi bạn truy cập một chỉ số mảng nằm ngoài giới hạn lúc chạy?
3. let zeros = [0; 5]; tạo ra gì?
Điểm: 0 / 3
Đọc thêm
Phần tiêu đề “Đọc thêm”- The Array Type — The Rust Book (tiếng Anh): phần giới thiệu chính thức về mảng, gồm cả lý do độ dài là một phần của kiểu.
- Arrays and Slices — Rust by Example (tiếng Anh): các ví dụ ngắn chạy được, kèm cái nhìn đầu tiên về slice.
- Looping Through a Collection with
for— The Rust Book (tiếng Anh): vì sao vòng lặpforan toàn hơn việc đi qua mảng bằng chỉ số. array— tài liệu thư viện chuẩn (tiếng Anh): những gì mảng làm được, nhưmapvàas_slice, và cách mảng mượn được mọi phương thức của slice.