【Rust练习】22.HashMap

练习题来自 https://practice-zh.course.rs/collections/hashmap.html

1

rust 复制代码
// 填空并修复错误
use std::collections::HashMap;
fn main() {
    let mut scores = HashMap::new();
    scores.insert("Sunface", 98);
    scores.insert("Daniel", 95);
    scores.insert("Ashley", 69.0);
    scores.insert("Katie", "58");

    // get 返回一个 Option<&V> 枚举值
    let score = scores.get("Sunface");
    assert_eq!(score, Some(98));

    if scores.contains_key("Daniel") {
        // 索引返回一个值 V
        let score = scores["Daniel"];
        assert_eq!(score, __);
        scores.remove("Daniel");
    }

    assert_eq!(scores.len(), __);

    for (name, score) in scores {
        println!("The score of {} is {}", name, score)
    }
}

这个insert语法和C++其实差不了多少。

rust 复制代码
    let mut scores = HashMap::new();
    scores.insert("Sunface", 98);
    scores.insert("Daniel", 95);
    scores.insert("Ashley", 69);
    scores.insert("Katie", 58);

这里应该是&i32

rust 复制代码
    // get 返回一个 Option<&V> 枚举值
    let score = scores.get("Sunface");
    assert_eq!(score, Some(&98));

这部分的操作和C++也差不多

rust 复制代码
    if scores.contains_key("Daniel") {
        // 索引返回一个值 V
        let score = scores["Daniel"];
        assert_eq!(score, 95);
        scores.remove("Daniel");
    }

    assert_eq!(scores.len(), 3);

2

rust 复制代码
use std::collections::HashMap;
fn main() {
    let teams = [
        ("Chinese Team", 100),
        ("American Team", 10),
        ("France Team", 50),
    ];

    let mut teams_map1 = HashMap::new();
    for team in &teams {
        teams_map1.insert(team.0, team.1);
    }

    // 使用两种方法实现 team_map2
    // 提示:其中一种方法是使用 `collect` 方法
    let teams_map2...

    assert_eq!(teams_map1, teams_map2);

    println!("Success!")
}

最好的方法就是将team1转迭代器,再转成集合类型:

rust 复制代码
let teams_map2:HashMap<&str, i32> = teams.into_iter().collect();

或者像上面一样也行,但是需要让map mutable

rust 复制代码
    let mut teams_map2 = HashMap::new();
    for team in &teams {
        teams_map2.insert(team.0, team.1);
    }

3

rust 复制代码
// 填空
use std::collections::HashMap;
fn main() {
    // 编译器可以根据后续的使用情况帮我自动推断出 HashMap 的类型,当然你也可以显式地标注类型:HashMap<&str, u8>
    let mut player_stats = HashMap::new();

    // 查询指定的 key, 若不存在时,则插入新的 kv 值
    player_stats.entry("health").or_insert(100);

    assert_eq!(player_stats["health"], __);

    // 通过函数来返回新的值
    player_stats.entry("health").or_insert_with(random_stat_buff);
    assert_eq!(player_stats["health"], __);

    let health = player_stats.entry("health").or_insert(50);
    assert_eq!(health, __);
    *health -= 50;
    assert_eq!(*health, __);

    println!("Success!")
}

fn random_stat_buff() -> u8 {
    // 为了简单,我们没有使用随机,而是返回一个固定的值
    42
}

得益于Rust后来居上,可以实现一些C++的map没有的东西,比如这个找不到自动插入的or_insert(更像是语法糖,我感觉)这也和C++标准委员会这么多年以来确实没加入啥新东西有关。另外,Rust居然可以对右值进行引用,这种操作在C++里根本实现不了,着实需要我一段时间去适应。

rust 复制代码
// 填空
use std::collections::HashMap;
fn main() {
    // 编译器可以根据后续的使用情况帮我自动推断出 HashMap 的类型,当然你也可以显式地标注类型:HashMap<&str, u8>
    let mut player_stats = HashMap::new();

    // 查询指定的 key, 若不存在时,则插入新的 kv 值
    player_stats.entry("health").or_insert(100);

    assert_eq!(player_stats["health"], 100);

    // 通过函数来返回新的值
    player_stats.entry("health").or_insert_with(random_stat_buff);
    assert_eq!(player_stats["health"], 100);

    let health = player_stats.entry("health").or_insert(50);
    assert_eq!(health, &100);
    *health -= 50;
    assert_eq!(*health, 50);

    println!("Success!")
}

fn random_stat_buff() -> u8 {
    // 为了简单,我们没有使用随机,而是返回一个固定的值
    42
}

4

rust 复制代码
// 修复错误
// 提示: `derive` 是实现一些常用特征的好办法
use std::collections::HashMap;

struct Viking {
    name: String,
    country: String,
}

impl Viking {
    fn new(name: &str, country: &str) -> Viking {
        Viking {
            name: name.to_string(),
            country: country.to_string(),
        }
    }
}

fn main() {
    // 使用 HashMap 来存储 viking 的生命值
    let vikings = HashMap::from([
        (Viking::new("Einar", "Norway"), 25),
        (Viking::new("Olaf", "Denmark"), 24),
        (Viking::new("Harald", "Iceland"), 12),
    ]);

    // 使用 derive 的方式来打印 viking 的当前状态
    for (viking, health) in &vikings {
        println!("{:?} has {} hp", viking, health);
    }
}

我想说一下自定义类型作为key的这个问题。C++如果想让结构体作为map的key,要么需要结构体本身重载了大于号或者小于号,函数还必须是const的:

cpp 复制代码
struct Stu
{
    Stu(int age) : age(age) {}
    bool operator<(const Stu &rhs) const { return this->age < rhs.age; }
    int age;
};

int main()
{
    Stu stu1{1};
    Stu stu2{2};
    pair p1 = {stu1, 1};
    pair p2 = {stu2, 2};
    map<Stu, int> mapp;
    mapp.insert(p1);
    mapp.insert(p2);
    return 0;
}

要么需要map定义时,传入一个比较函数:

否则就会出现这种报错:

cpp 复制代码
struct Compare
{
    bool operator()(const Stu &rhs1, const Stu &rhs2) const
    {
        return rhs1.age < rhs2.age;
    }
};

int main()
{
    Stu stu1{1};
    Stu stu2{2};
    pair p1 = {stu1, 1};
    pair p2 = {stu2, 2};
    map<Stu, int, Compare> mapp;
    mapp.insert(p1);
    mapp.insert(p2);
    return 0;
}

回到这道题,用derive即可,反正都是基本类型。

rust 复制代码
#[derive(PartialEq, Eq, Hash, Debug)]
struct Viking {
    name: String,
    country: String,
}

另外关于partialeq eq区别,我看了,也没看懂,以后写到再说。

5

rust 复制代码
// 修复错误,尽可能少的去修改代码
// 不要移除任何代码行!
use std::collections::HashMap;
fn main() {
  let v1 = 10;
  let mut m1 = HashMap::new();
  m1.insert(v1, v1);
  println!("v1 is still usable after inserting to hashmap : {}", v1);

  let v2 = "hello".to_string();
  let mut m2 = HashMap::new();
  // 所有权在这里发生了转移
  m2.insert(v2, v1);

  assert_eq!(v2, "hello");

   println!("Success!")
}

改成引用就好了

rust 复制代码
m2.insert(&v2, v1);
相关推荐
lypzcgf2 分钟前
Coze源码分析-资源库-删除插件-后端源码-应用和领域服务层
后端·go·coze·coze插件·coze源码分析·智能体平台·ai应用平台
lssjzmn7 分钟前
Spring Web 异步响应实战:从 CompletableFuture 到 ResponseBodyEmitter 的全链路优化
java·前端·后端·springboot·异步·接口优化
shark_chili12 分钟前
程序员必知的底层原理:CPU缓存一致性与MESI协议详解
后端
一只乔哇噻27 分钟前
java后端工程师进修ing(研一版 || day41)
java·开发语言·学习·算法
愿时间能学会宽恕28 分钟前
SpringBoot后端开发常用工具详细介绍——SpringSecurity认证用户保证安全
spring boot·后端·安全
钮钴禄·爱因斯晨37 分钟前
深入剖析LLM:从原理到应用与挑战
开发语言·人工智能
CodeSheep43 分钟前
稚晖君又开始摇人了,有点猛啊!
前端·后端·程序员
小宁爱Python1 小时前
Django 从环境搭建到第一个项目
后端·python·django
六点半8881 小时前
【C++】C++11 篇二
开发语言·c++
uzong1 小时前
深入浅出:画好技术图
后端·架构