Vector trong Rust
Vector (Vec) giống như một mảng, nhưng có thể dài ra và ngắn lại lúc chạy. Trong code Rust hằng ngày, khi cần một danh sách, bạn sẽ dùng Vec thường xuyên hơn nhiều so với mảng có kích thước cố định.
Tạo một vector
Phần tiêu đề “Tạo một vector”fn main() { let numbers: Vec<i32> = vec![1, 2, 3]; println!("{:?}", numbers);}vec![] là một macro (để ý dấu !) tạo ra một Vec từ danh sách giá trị, tương tự như cách bạn viết một mảng.
Bạn cũng có thể bắt đầu với một vector rỗng rồi thêm dần vào:
let mut numbers: Vec<i32> = Vec::new();Thêm phần tử
Phần tiêu đề “Thêm phần tử”Dùng .push() để thêm vào cuối. Vector cần là mut vì bạn đang thay đổi nó:
fn main() { let mut numbers = Vec::new();
numbers.push(1); numbers.push(2); numbers.push(3);
println!("{:?}", numbers);}Kết quả:
[1, 2, 3]Truy cập phần tử
Phần tiêu đề “Truy cập phần tử”Cùng cú pháp ngoặc vuông như mảng:
fn main() { let fruits = vec!["táo", "chuối", "anh đào"];
println!("{}", fruits[0]); println!("Độ dài: {}", fruits.len());}Để tra cứu an toàn hơn mà không panic khi chỉ số sai, hãy dùng .get(), nó trả về một Option (xem thêm trong bài Option):
fn main() { let fruits = vec!["táo", "chuối", "anh đào"];
match fruits.get(10) { Some(fruit) => println!("Tìm thấy: {fruit}"), None => println!("Không có loại quả nào ở chỉ số đó"), }}Xóa phần tử
Phần tiêu đề “Xóa phần tử”fn main() { let mut numbers = vec![1, 2, 3, 4, 5];
numbers.pop(); // xóa phần tử cuối -> [1, 2, 3, 4] numbers.remove(0); // xóa theo chỉ số -> [2, 3, 4]
println!("{:?}", numbers);}Duyệt qua một vector
Phần tiêu đề “Duyệt qua một vector”fn main() { let numbers = vec![10, 20, 30];
for n in &numbers { println!("{n}"); }}Để ý dấu & trước numbers — duyệt bằng for n in &numbers sẽ mượn (borrow) từng phần tử thay vì lấy quyền sở hữu cả vector. Bỏ dấu & đi thì vector bị move vào vòng lặp, nghĩa là bạn không thể dùng numbers sau đó nữa. Hầu như lúc nào bạn cũng muốn mượn.
Đôi lời về generic
Phần tiêu đề “Đôi lời về generic”Bạn sẽ để ý kiểu được viết là Vec<i32> — phần <i32> nói rằng “một vector chứa các giá trị i32.” Cách viết với dấu ngoặc nhọn này gọi là generic, và bạn sẽ gặp lại nó đầy đủ trong bài Generic. Bây giờ, chỉ cần đọc Vec<T> là “một vector chứa các giá trị kiểu T.”
Luyện tập
Phần tiêu đề “Luyện tập”1. Gom các số chẵn
Phần tiêu đề “1. Gom các số chẵn”Bắt đầu với một vector rỗng. Duyệt qua các số từ 1 đến 10 và chỉ push các số chẵn. Sau đó in vector và số phần tử của nó. Gợi ý: số n là số chẵn khi n % 2 == 0.
Xem lời giải
fn main() { let mut evens = Vec::new();
for n in 1..=10 { if n % 2 == 0 { evens.push(n); } }
println!("{:?}", evens); println!("Tìm thấy {} số chẵn", evens.len());}Kết quả:
[2, 4, 6, 8, 10]Tìm thấy 5 số chẵnĐể ý rằng ta không hề ghi kiểu. Rust nhìn vào các lệnh gọi push(n) và tự suy ra evens là một Vec<i32>.
2. Chồng đĩa
Phần tiêu đề “2. Chồng đĩa”Push ba cái đĩa vào một vector: "xanh dương", "xanh lá", rồi "đỏ". Lấy hai cái đĩa trên cùng ra bằng .pop() và in từng cái. Cuối cùng, in ra những gì còn lại. Gợi ý: .pop() trả về một Option, nên hãy in nó bằng {:?}.
Xem lời giải
fn main() { let mut plates = Vec::new(); plates.push("xanh dương"); plates.push("xanh lá"); plates.push("đỏ");
println!("Lấy ra {:?}", plates.pop()); println!("Lấy ra {:?}", plates.pop()); println!("Còn lại: {:?}", plates);}Kết quả:
Lấy ra Some("đỏ")Lấy ra Some("xanh lá")Còn lại: ["xanh dương"]pop() luôn lấy phần tử cuối cùng mà bạn đã push, giống như nhấc cái đĩa trên cùng khỏi chồng đĩa. Nó trả về Some(...), chứ không phải giá trị trần, vì vector có thể đang rỗng. Khi đó bạn sẽ nhận None thay vì chương trình bị crash.
Tóm tắt
Phần tiêu đề “Tóm tắt”Vec<T>là danh sách có thể co giãn; tạo bằngvec![...]hoặcVec::new()..push()thêm vào cuối;.pop()xóa phần tử cuối;.remove(i)xóa theo chỉ số.vec[i]panic khi chỉ số sai;.get(i)thì trả về mộtOption, không panic.- Duyệt bằng
for item in &vecđể mượn từng phần tử thay vì tiêu thụ cả vector.
Kiểm tra nhanh
Phần tiêu đề “Kiểm tra nhanh”Kiểm tra nhanh
1. Điều gì xảy ra khi bạn truy cập một Vec bằng chỉ số sai, như numbers[10]?
2. Phương thức nào cho phép tra cứu theo chỉ số mà không có nguy cơ panic?
3. Dấu & trong for n in &numbers làm gì?
Điểm: 0 / 3
Đọc thêm
Phần tiêu đề “Đọc thêm”- Storing Lists of Values with Vectors — The Rust Book (tiếng Anh): tạo, đọc và cập nhật vector, và vì sao bạn không thể push khi đang giữ một tham chiếu.
- Vectors — Rust by Example (tiếng Anh): một ví dụ chạy được thể hiện các thao tác
Vecphổ biến nhất. Vec— tài liệu thư viện chuẩn (tiếng Anh): danh sách đầy đủ các phương thức, nhưinsert,retain,extendvàcontains.- Macro
vec!— tài liệu thư viện chuẩn (tiếng Anh): mọi dạng củavec!, gồm cảvec![0; 10]cho giá trị lặp lại.