通用集合类型

2023/3/11
  • 动态数组(vector)可以让你连续地存储任意多个值。

  • 字符串(string)是字符的集合。

  • 哈希映射(hash map)可以让你将值关联到⼀个特定的键上,它是另外⼀种数据结构—映射 (map)的特殊实现。

# 动态数组

// #[derive(Debug)]

fn main() {
    // 1.创建动态数组
    // 创建⼀个⽤来存储i32数据的空动态数组
    let v1: Vec<i32> = Vec::new();
    // 使⽤初始值去创建动态数组
    let v2 = vec![1, 2, 3];

    // 2.更新动态数组
    let mut v3 = Vec::new();
    v3.push(5);
    v3.push(6);
    v3.push(7);

    // 3.读取动态数组中的元素
    let v4 = vec![1, 2, 3, 4, 5, 6];

    // 索引方式读取
    let third: &i32 = &v4[2];
    println!("the third element is {}", third);
    // get方法读取 v4.get(2)类型Option<&i32>
    match v4.get(2) {
        Some(third_2) => println!("the third element is {}", third_2),
        None => println!("There is no third element."),
    }

    // 4.遍历动态数组中的值
    let v5 = vec![100, 32, 57];
    for i in &v5 {
        // i 数组中的值
        println!("{}", i)
    }

    // 5.使用枚举来存储多个类型的值

    enum SpreadsheetCell {
        Int(i32),
        Float(f64),
        Text(String),
    }

    let row = vec![
        SpreadsheetCell::Int(3),
        SpreadsheetCell::Text(String::from("blue")),
        SpreadsheetCell::Float(10.12),
    ];
}

# 字符串

// #[derive(Debug)]

fn main() {
    // 1.创建字符串
    // 创建空字符串
    let mut s1 = String::new();

    // to_string⽅法基于字符串字⾯量创建String
    let data = "initial contents";
    let s2 = data.to_string();

    // 使⽤String::from函数基于字符串字⾯量创建String
    let s3 = String::from("hello world");

    // 2.更新字符串
    let mut s4 = String::from("foo");
    s4.push_str("bar"); // foobar

    // 将⼀个字符添加到String中 char 类型
    s4.push('1'); // foobar1

    // 拼接字符串
    let s5 = String::from("Hello,");
    let s6 = String::from("world");
    let s7 = s5 + &s6; // 注意这⾥的s5已经被移动且再也不能被使⽤了

    // 使用format!宏拼接
    let s8 = String::from("tic");
    let s9 = String::from("tac");
    let s10 = String::from("toe");
    let s11 = format!("{}{}{}", s8, s9, s10); // tictactoe

    // 3.遍历字符串的⽅法
    // 打印chat
    for c in "abcd".chars() {
        println!("{}", c)
    }
    // 打印byte
    for c in "abcd".bytes() {
        println!("{}", c)
    }
}

# 哈希映射

// #[derive(Debug)]

use std::collections::HashMap;

fn main() {
    // 1.创建一个哈希映射
    let mut scores = HashMap::new();
    scores.insert(String::from("Blue"), 10);
    scores.insert(String::from("Yellow"), 50);

    // 动态数组转换为哈希映射
    let teams = vec![String::from("Blue"), String::from("Yellow")];
    let initial_scores = vec![10, 50];

    // 类型标记HashMap<_, _>不能被省略,
    // 因为collect可以作⽤于许多不同的数据结构,如果不指明类型的话,
    // Rust就⽆法知道我们具体想要的类型。但是对于键值的类型参数,我们则使⽤了下画线占位
    let scores2: HashMap<_, _> = teams.iter().zip(initial_scores.iter()).collect();

    // 2.访问哈希映射中的值
    let team_name = String::from("Blue");
    let score = scores.get(&team_name);

    // 遍历
    for (key, value) in &scores {
        println!("{}:{}", key, value)
    }

    // 3.更新哈希映射
    // 覆盖旧值
    scores.insert(String::from("Blue"), 10);
    scores.insert(String::from("Blue"), 20);

    // 如果该分数值不存在,就将50作为初始值插⼊
    scores.insert(String::from("Blue"), 10);
    scores.entry(String::from("Yellow2")).or_insert(50);
    scores.entry(String::from("Blue")).or_insert(50);
    // 输出 {Yellow2:50,Blue:10}

    // 基于旧值来更新值
    let text = "hello world wonderful world";
    let mut map = HashMap::new();

    for word in text.split_whitespace() {
        let count = map.entry(word).or_insert(0);
        // 代码中的⽅法or_insert实际上为我们传⼊的键返回了⼀个指向关联值的可
        // 变引⽤(&mut V)。这个可变引⽤进⽽被存储到变量count上,为了对
        // 这个值进⾏赋值操作,我们必须⾸先使⽤星号(*)来对count进⾏解
        // 引⽤。由于这个可变引⽤会在for循环的结尾处离开作⽤域,所以我们
        // 在代码中的所有修改都是安全且满⾜借⽤规则的。
        *count += 1;
    }
    println!("{:?}", map); // {"world": 2, "hello": 1, "wonderful": 1}
}