这是最高级别的niveau的抱怨,但我解决了rustlings课程中的一项任务,我相信这不是最佳解决方案,甚至不是一个好的解决方案。
任务:https://github.com/rust-lang/rustlings/blob/main/exercises/hashmaps/hashmaps3.rs
我的解决方案(仅相关部分(:
fn build_scores_table(results: String) -> HashMap<String, Team> {
// The name of the team is the key and its associated struct is the value.
let mut scores: HashMap<String, Team> = HashMap::new();
for r in results.lines() {
let v: Vec<&str> = r.split(',').collect();
let team_1_name = v[0].to_string();
let team_1_score: u8 = v[2].parse().unwrap();
let team_2_name = v[1].to_string();
let team_2_score: u8 = v[3].parse().unwrap();
let team_1 = scores.entry(team_1_name.clone()).or_insert(Team {
name: team_1_name.clone(),
goals_scored: 0,
goals_conceded: 0,
});
team_1.goals_scored += team_1_score;
team_1.goals_conceded += team_2_score;
let team_2 = scores.entry(team_2_name.clone()).or_insert(Team {
name: team_2_name.clone(),
goals_scored: 0,
goals_conceded: 0,
});
team_2.goals_scored += team_2_score;
team_2.goals_conceded += team_1_score;
}
scores
}
我的问题是,我正在.entry()
方法内部和Team结构中克隆字符串(两次!(。我试着在没有的情况下使用它,但它不起作用(借用东西(,并使用&
,但它并不高兴,因为它期望String
而不是&String
。
不确定什么不起作用?你可以在第二个使用网站上移动,它运行良好:
let team_1 = scores.entry(team_1_name.clone()).or_insert(Team {
name: team_1_name,
goals_scored: 0,
goals_conceded: 0,
});
team_1.goals_scored += team_1_score;
team_1.goals_conceded += team_2_score;
如果你想在成功的情况下进行零克隆(团队已经有了条目(,代码就不那么性感了,但它也编译得很好:
if let Some(t) = scores.get_mut(&team_1_name) {
t.goals_scored += team_1_score;
t.goals_conceded += team_2_score;
} else {
scores.insert(team_1_name.clone(), Team {
name: team_1_name,
goals_scored: team_1_score,
goals_conceded: team_2_score,
});
}
从技术上讲,我们甚至可以删除初始to_string
,在命中情况下不进行分配(显然,这意味着在未命中情况下进行两次分配(:
let team_1_name = v[0];
let team_1_score: u8 = v[2].parse().unwrap();
// ...
if let Some(t) = scores.get_mut(team_1_name) {
t.goals_scored += team_1_score;
t.goals_conceded += team_2_score;
} else {
scores.insert(team_1_name.to_string(), Team {
name: team_1_name.to_string(),
goals_scored: team_1_score,
goals_conceded: team_2_score,
});
}
或者,从Team
结构中删除name
,这并没有真正的价值,因为您有hashmap键。虽然在这一点上,您不再有Team
结构,所以它可能应该重命名,例如Score
或Goals
(您可以从剩下的两个成员中去掉前缀(。
您不需要第二个.clone()
调用(在Team
中(,因为您可以允许结构获得该调用的所有权,因为之后没有其他调用使用它。他们设置的哈希图对你来说有点奇怪,因为键和值都包含团队名称。如果您只是从结构定义中删除它,就不需要再进行克隆了(无论如何,它永远不会被使用(。
struct Team {
goals_scored: u8,
goals_conceded: u8,
}
fn build_scores_table(results: String) -> HashMap<String, Team> {
// The name of the team is the key and its associated struct is the value.
let mut scores: HashMap<String, Team> = HashMap::new();
for r in results.lines() {
let v: Vec<&str> = r.split(',').collect();
let team_1_name = v[0].to_string();
let team_1_score: u8 = v[2].parse().unwrap();
let team_2_name = v[1].to_string();
let team_2_score: u8 = v[3].parse().unwrap();
let team_1 = scores.entry(team_1_name).or_insert(Team {
goals_scored: 0,
goals_conceded: 0,
});
team_1.goals_scored += team_1_score;
team_1.goals_conceded += team_2_score;
let team_2 = scores.entry(team_2_name).or_insert(Team {
goals_scored: 0,
goals_conceded: 0,
});
team_2.goals_scored += team_2_score;
team_2.goals_conceded += team_1_score;
}
scores
}
这就是我最终得到的结果,而不是疯狂地使用"和_ diffy";两次,但都是生活。
fn build_scores_table(results: String) -> HashMap<String, Team> {
let mut scores: HashMap<String, Team> = HashMap::new();
for r in results.lines() {
let v: Vec<&str> = r.split(',').collect();
let team_1_name = v[0].to_string();
let team_1_score: u8 = v[2].parse().unwrap();
let team_2_name = v[1].to_string();
let team_2_score: u8 = v[3].parse().unwrap();
scores.entry(team_1_name.clone())
.and_modify(|a| a.goals_scored += team_1_score)
.and_modify(|b| b.goals_conceded += team_2_score)
.or_insert(Team { name: team_1_name,
goals_scored: team_1_score,
goals_conceded: team_2_score });
scores.entry(team_2_name.clone())
.and_modify(|a| a.goals_scored += team_2_score)
.and_modify(|b| b.goals_conceded += team_1_score)
.or_insert(Team { name: team_2_name,
goals_scored: team_2_score,
goals_conceded: team_1_score });
}
scores
}
学习一些东西!非常感谢。
顺便说一句,我有一个后续问题:与《铁锈》一书相比,为什么我们不能在这行中添加(*(
team_1.goals_scored += team_1_score;
成为
*team_1.goals_scored += team_1_score;
它失败的原因是什么?
我认为这与作为hashmap值的是类型Team
而不是基元类型这一事实有一定关系,但我仍然希望对此有一个清晰的理解。
关于后续问题,您尝试过以下方法吗:
(*team_1).goals_scored += team_1_score;