Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

collections/hashmap #172

giscus[bot] bot announced in Book Comments
Mar 28, 2022 · 15 comments · 9 replies
Discussion options

collections/hashmap

Learning Rust By Practice, narrowing the gap between beginner and skilled-dev with challenging examples, exercises and projects.

https://zh.practice.rs/collections/hashmap.html

You must be logged in to vote

Replies: 15 comments 9 replies

Comment options

题目2 的答案有误
let teams_map2: HashMap<,> = teams.into_iter().collect();
collect 会报错, value of type HashMap<&str, i32> cannot be built from std::iter::Iterator<Item=&(&str, i32)>
需改成 let teams_map2: HashMap<,> = teams.iter().cloned().collect();
原理我还在研究

You must be logged in to vote
2 replies
Comment options

个人猜测:
collect 会涉及到所有权的转换问题,需要先 cloned()/copid(),加完 clone(),会有个 warning
warning: this method call resolves to <&[T; N] as IntoIterator>::into_iter (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021
into_iter -> iter 这 warning 没看懂

Comment options

...... 这是edition = "2018" 才有的问题,edition = "2021" 就没这问题了

Comment options

第五题从哪里可以体现出需要自反性呢?

You must be logged in to vote
2 replies
Comment options

第五题不是所有权的问题吗?自反性是啥

Comment options

自反性:自己 == 自己,如果是浮点数的话就不满足自反性

Comment options

有点奇怪,
vec使用into_iter()时候是会消耗vec的,为什么下面这句话没有把teams所有权给消耗掉?
let teams_map2 = teams.into_iter().collect(); //

而使用下面iter()代替into_iter()时候反而出现了,上面@quarksb
说的edition = "2018" 才有的问题
let teams_map2 = teams.iter().collect(); //

You must be logged in to vote
3 replies
Comment options

Here are the reasons:

  1. teams is a array, not a vector.
  2. array is primitive type, and it implements Copy and Clone traits in default.

Thus, teams.into_iter() would not consume the ownership. In fact, it copy the array and convert the copied array into a new iterator.

If I missed anything, please let me know. THX!

References:

  1. array
Comment options

@twandylue Thanks your answer!

Comment options

楼上是对的,into_iter()确实会取得所有权,但如果每个元素都实现了copy,那它会直接复制,而不会移动。

Comment options

mark

You must be logged in to vote
0 replies
Comment options

lala

You must be logged in to vote
0 replies
Comment options

1、HashMap的基本操作

use std::collections::HashMap;
fn main() {
 let mut scores = HashMap::new();
 //需要保持<key,value>类型一致
 scores.insert("Sunface", 98);
 scores.insert("Daniel", 95);
 scores.insert("Ashley", 69);
 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, 95);
 scores.remove("Daniel");
 }
 assert_eq!(scores.len(), 3);
 for (name, score) in scores {
 println!("The score of {} is {}", name, score)
 }
}

2、

(1)collect的用法

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:HashMap<_,_>=teams.into_iter().collect();
 assert_eq!(teams_map1, teams_map2);
 println!("Success!")
}

(2)暴力复制

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=teams_map1.clone();
 assert_eq!(teams_map1, teams_map2);
 println!("Success!")
}

3、理解

// 填空
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、

// 修复错误
// 提示: `derive` 是实现一些常用特征的好办法
use std::collections::HashMap;
#[derive(Eq,Hash,PartialEq,Debug)]
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);
 }
}

5、所有权会被 HashMap调用

// 修复错误,尽可能少的去修改代码
// 不要移除任何代码行!
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.clone(), v1);
 assert_eq!(v2, "hello");
 println!("Success!")
}
You must be logged in to vote
2 replies
Comment options

第四题不明白,struct Viking {
name: String,
country: String,
}内都是String,String原来就有实现Hash和Eq,那这个结构体应该也是自动实现了Viking才对。为什么仍然要加#[derive(Hash, Eq, PartialEq, Debug)]才不报错呢?

Comment options

应该是结构体不会自动实现,而集合会

Comment options

done

You must be logged in to vote
0 replies
Comment options

  • done
You must be logged in to vote
0 replies
Comment options

three way to solve question number 2:

use std::collections::HashMap;

fn main() {
let teams : [(&str, i32); 3] = [
("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);
}
// IMPLEMENT team_map2 in two ways
// Tips: one of the approaches is to use `collect` method
// let teams_map2 : HashMap<&str, i32> = teams.into();
// let teams_map2 : HashMap<&str, i32> = teams.into_iter().collect();
let teams_map2 : HashMap<&str, i32> = HashMap::from(teams);
assert_eq!(teams_map1, teams_map2);
println!("Success!");

}

You must be logged in to vote
0 replies
Comment options

done~~~

You must be logged in to vote
0 replies
Comment options

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

宇宙的终极答案(

You must be logged in to vote
0 replies
Comment options

mark finished

You must be logged in to vote
0 replies
Comment options

Day 10
Done✅

You must be logged in to vote
0 replies
Comment options

Success(5/5)

You must be logged in to vote
0 replies
Comment options

done

You must be logged in to vote
0 replies
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

AltStyle によって変換されたページ (->オリジナル) /