Vector
Vector 資列結構中集合的一種: 可用來放置多個元素,特色為 可變長度,但元素需同型別。 但是,可以藉由 enum variants 特性,讓 Vector 裝載不同型別元素
有別於 Tuple 與 Array。
Tuple:固定長度,元素需同型別。
Array:固定長度,元素不要求同型別Vector 允許 遍歷並改值 : 🖍️ 特殊,大部分語言並不允許
Vector 建構方式
Vector 可經由 new 建立 instance,並搭配 push 增加元素。
也可經由 vec macro 建立時一併指定元素。
Vector : 基本建構方式 new
let mut shopping_cart: Vec<&str> = Vec::new();
shopping_cart.push("Book");
shopping_cart.push("Pen");
shopping_cart.push("Eraser");
shopping_cart.push("Ruler");
Vector : 經由 Macro 建構
- rust 提供了 vec! 巨集,用來快速建立 vector。
 
pub fn use_macro_to_init_vector() {
    let v:Vec<&str> = vec!["A", "B", "C"];
    for i in &v {
        println!("{i}");
    }
}
Vector 基本使用方式
自 Vector 中選取元素
兩種方式: by index 與 by get method
by index: Array 相同經由角括號指定 index。Tuple 方式最怪異,直接以點取值。
by get method: 與 Java 相同可以以 get(index) 方法取出 Option 再搭配 option.unwrap() 取值。
pub fn create_vector() {
    let mut shopping_cart: Vec<&str> = Vec::new();
    shopping_cart.push("Book");
    shopping_cart.push("Pen");
    shopping_cart.push("Eraser");
    shopping_cart.push("Ruler");
    //& 記憶體借用
    for item in &shopping_cart {
        println!("{item}");
    }
    // Vector 取值方式, by index, by get
    // 索引語法
    let second: &str = shopping_cart[1];
    println!("The 2nd is: {second}");
    //The 2nd is Pen
    // get 語法: 可先取出 Option
    let get_second: Option<&&str> = shopping_cart.get(1);
    match get_second {
        Some(get_second) => println!("Get 2nd: {get_second}"), //Get 2nd: Pen, 不用 unwrap?
        None => println!("Not exists: {:?}", get_second),  //Not exists: None
    }
    // Vector 先取出 Option 再解包取值
    if (get_second != None) {
        println!("2nd.unwrap is not None: {}", get_second.unwrap());
        // 2nd.unwrap is not None: Pen
        println!("2nd.unwrap is not None ?: : {:?}", get_second.unwrap());
        // 2nd.unwrap is not None ?: : "Pen"
        println!("2nd is not None ?: : {:?}", get_second);
        // 2nd is not None ?: : Some("Pen")
    }
}
Vector 迴圈走訪方式
Vector 允許 遍歷並改值 : 🖍️ 特殊,大部分語言並不允許
Vector 走訪: for each
- 使用 rust iterator 來 lazy 走訪。
 - v.iter() 僅是建立迭代器。
 
let v = vec![1, 2, 3]; 
for i in v.iter() { 
    println!("{}", i); 
}
let some_vec = vec![1, 2, 3];
for i in &some_vec {
    println!("{}", i);
}
Vector 走訪: enumerate
let vec = vec![1, 2, 3]; 
for (index, element) in vec.enumerate() { 
    println!("The element:{} is {}", index, element); 
}
DSL: Java Collection 中的 stream
- vectorA.iter().map(|x| / do something here /)
 - vec.into_iter() : alloc::vec::into_iter::IntoIter\<T>
 - 跟 Java stream 相同,這邊的動作具 Lazy 特性
 
//looping
let vec = vec![1, 2, 3]; 
let doubled: Vec<i32> = vec.into_iter().map(|x| x * 2).collect(); 
//vec.into_iter() : alloc::vec::into_iter::IntoIter<T>   
println!("{:?}", doubled); // [2, 4, 6]
語法比較
//java
List x = collection.stream().map((item) -> do something with item).collect(toList());
// (item) -> , 小括號做signature,箭頭引出實作
//rust
let x2: Vec = vec.into_iter().map(|item| do something with item ).collect(); 
// |item| , 省略箭頭, 雙槓 || 做 signature,後方直接附加實作
🖍️ 遍歷並改值 🖍️ 
- 使用 解參考 operator * ,並給予新值。
 
pub fn iteration_go_with_modification() {
    let mut vect: Vec<i32> = vec![1 , 2, 3];
    println!("一般迴圈走訪");
    for item in &vect {
        println!("{item}");
    }
    println!("走訪,解參考並異動");
    for item in &mut vect { //取得可變參考, 
        *item = item.clone() * 10; //使用解參考運算子,改數值。
    }
    for item in &vect {
        println!("{item}");
    }
    // Iterate and Modify
    // 10
    // 20
    // 30
}
Vector 裝載不同型別元素
藉由 Rust enum variant 的特殊特性,也就是每個 variant 可以具備各自特有的 fields。
藉由這個特性讓每個 enum instance 把持一個特定的型別。
再將這些 enum instances 存在 Vector 之中。
- 使用重點:
- enum variants 建立方式
 - 自 enum instance 中取出 field 內容(unpacking)
 
 
enum TextFieldDataType {
    StringType(String),
    DateType(DateTime<Utc>),
    NumericType(i32),
}
pub fn vector_multitype_elements() {
    // 以 Vector 存多個 TextFieldDataType
    // 每個 TextFieldDataType 攜帶一個不同型別的資料
    let multi: Vec<TextFieldDataType> = vec![
        TextFieldDataType::StringType(String::from("Totem Study Rust")),
        TextFieldDataType::NumericType(100),
        TextFieldDataType::DateType(Utc::now()),
    ];
    for item in &multi {
        // 這邊的範例是將不同型別元素轉成 string 來呈現。
        let mut value = String::from("");
       // # 取出 TextFieldDataType 所攜帶的資料,並統一轉成 String 進行後續處理。
       // 這邊牽涉到 Rust 資料解包 (unpacking)
        match item {
            TextFieldDataType::StringType(field) => {
                value = field.clone();
            }
            TextFieldDataType::NumericType(number) => {
               value = number.to_string();
            }
            TextFieldDataType::DateType(date) => {
                value = format!("{}", date);
            }
        }
        println!("{}", value);
    }
}
v.iter() vs v.into_iter() 差異
- *i
 
//looping + in-place modification
let mut some_vec = vec![1, 2, 3];
some_vec.iter_mut().for_each(|i| *i *= 2);
println!("{:?}", some_vec); // [2, 4, 6]