
Learn Rust: Basic Vector
Vector
Rust มี Vector type สำหรับเก็บข้อมูล type เดียวกันหลาย ๆ ค่า (collection) แต่ต่างจาก array ตรงที่ Vector เป็นแบบ dynamic size สามารถเพิ่ม ลด ขนาดของข้อมูลได้ และสามารถเก็บข้อมูลได้หลาย ๆ ค่า โดยไม่ต้องระบุขนาดของข้อมูลล่วงหน้า
Create Vector
เราสามารถสร้าง vector ใหม่ได้โดยเรียก associated function new
ของ Vec
เช่น
// Create Vector of i32 instance
let v: Vec<i32> = Vec::new();
println!("{:#?}", v);
จะเห็นว่า Vec มี generic type parameter ที่เราต้องระบุ type ของข้อมูลที่จะเก็บไว้ใน vector นั้น ๆ ในตัวอย่างนี้เรากำหนดให้เก็บข้อมูลเป็น i32
ถ้าเราต้องการกำหนดค่าเริ่มต้นให้กับ vector เราสามารถใช้ macro vec!
ได้เช่น
// Create and intialize with vec! macro
let v = vec![1, 2, 3, 4];
println!("{:#?}", v);
Add Element to Vector
เราสามารถเพิ่มข้อมูลเข้าไปใน vector ได้โดยใช้ method push
เช่น
// Create mut Vector then push value
let mut v: Vec<i32> = Vec::new();
v.push(1);
v.push(2);
v.push(3);
v.push(4);
let v = v;
println!("{:#?}", v);
ซึ่งเราก็ต้องประกาศ vector เป็น mutable ก่อนเพื่อให้สามารถเพิ่มข้อมูลเข้าไปได้
Access Element of Vector
เราสามารถเข้าถึงข้อมูลใน vector ได้โดยใช้ index ของข้อมูล ซึ่ง index เริ่มที่ 0 เช่น
// get value by index start with zero
let one = v[0];
let two = v[1];
let three = v[2];
let four = v[3];
println!("{one}, {two}, {three}, {four}");
ถ้าเราใช้ index ที่เกินขนาดของ vector Rust จะ panic และจบการทำงานของโปรแกรม ดังนี้
// panic if index out of bounds
let five = v[4];
หรือเราจะใช้ method get
ก็ได้เช่นกัน โดยที่ method get
จะ return Option<&T>
ซึ่งจะทำให้เราเช็คได้ว่า index ที่เราเรียกมีข้อมูลหรือไม่ ถ้ามีข้อมูลจะ return Some(&T)
ถ้าไม่มีข้อมูลจะ return None
ดังนี้
// get with get method that return Option<&T>
if let Some(five) = v.get(5) {
println!("found {five}");
} else {
println!("not found");
}
Iterate Over Vector
เนื่องจาก vector implements IntoIterator
trait เราสามารถ loop ข้อมูลใน vector ได้โดยใช้ for .. in
loop เช่น
// loop with for iterate on T, so v is move and cannot use after that
for i in v {
println!("{i}");
}
แต่การที่เราใช้ v
ตรง ๆ Iterator ที่ได้มันจะ move ตัว vector ไปใช้ใน Iterator ด้วยทำให้เราไม่สามารถใช้ v
ได้อีกหลังจาก loop เพราะ ownership ของ v
ถูกเปลี่ยนไปให้ Iterator แล้ว
ถ้าเราต้องการใช้ v
หลังจาก loop เราสามารถใช้ &v
แทนได้เพื่อให้ Iterator ใช้ reference ของ v
เป็นการ borrow แทน ดังนี้
// loop with for iterate on &T, so v is move and cannot use after that
for i in &v {
println!("{i}");
}
หรือถ้าเราอยากแก้ไขข้อมูลใน vector โดยใช้ loop เราสามารถใช้ &mut v
แทนได้เพื่อให้ Iterator ใช้ mutable reference ของ v
เป็นการ borrow แทน ดังนี้
let mut v = vec![1, 2, 3, 4];
// loop with for iterate on &mut T, so we can update element by using defer
for i in &mut v {
*i*=2; // double
}
println!("{:#?}", v);
Slice Vector
เราสามารถสร้าง slice ของ vector ได้โดยใช้ &
หน้า vector และ ..
ระหว่าง index ที่เราต้องการ slice เช่น
let s = &v[..];
println!("{:#?}", s);
let s = &v[1..];
println!("{:#?}", s);
let s = &v[1..2];
println!("{:#?}", s);
let s = &v[..2];
println!("{:#?}", s);
Deref to Slice of T
เนื่องจาก vector มี method deref
ที่ return slice ของ T ทำให้เราสามารถเรียก method ของ slice ได้โดยตรง เช่นเรียก iter() แบบนี้
let v = vec![1, 2, 3, 4];
for i in v.iter() {
println!("{i}");
}
สามารถดู method อื่น ๆ ของ vector ได้จาก Rust API Documentation