rustlings中HashMap无法使用方括号可变索引的问题咨询
Rust HashMap 可变方括号索引的疑问与解答
我在完成rustlings的hashmaps3.rs练习时产生了疑问:Rust本身支持用方括号索引返回可变值,但HashMap<K, V>是不是没实现这个功能?下面是具体的代码和尝试过程:
练习完整代码
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(); // TODO: Populate the scores table with details extracted from the // current line. Keep in mind that goals scored by team_1 // will be the number of goals conceded from team_2, and similarly // goals scored by team_2 will be the number of goals conceded by // team_1. } scores }
两种实现思路
第一种(可正常编译)
let team1 = scores.get_mut(&team_1_name); match team1 { Some(t) => { t.goals_scored += team_1_score; t.goals_conceded += team_2_score; }, None => { scores.insert(team_1_name, Team { goals_scored: team_1_score, goals_conceded: team_2_score }); } }
第二种(编译失败的尝试过程)
最初尝试用方括号索引修改,遇到一系列错误:
- 首次错误:
error[E0594]: cannot assign to `team2.goals_scored`, as `team2` is not declared as mutable --> exercises/hashmaps/hashmaps3.rs:62:9 | 62 | team2.goals_scored += team_2_score; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot assign | help: consider changing this to be mutable | 61 | let mut team2 = scores[&team_2_name]; | +++
- 按提示添加
mut后:
error[E0507]: cannot move out of index of `HashMap<String, Team>` --> exercises/hashmaps/hashmaps3.rs:61:25 | 61 | let mut team2 = scores[&team_2_name]; | ^^^^^^^^^^^^^^^^^^^^ move occurs because value has type `Team`, which does not implement the `Copy` trait | help: consider borrowing here | 61 | let mut team2 = &scores[&team_2_name]; | +
- 改成引用后:
warning: variable does not need to be mutable --> exercises/hashmaps/hashmaps3.rs:61:13 | 61 | let mut team2 = &scores[&team_2_name]; | ----^^^^^ | | | help: remove this `mut` | = note: `#[warn(unused_mut)]` on by default error[E0594]: cannot assign to `team2.goals_scored`, which is behind a `&` reference --> exercises/hashmaps/hashmaps3.rs:62:9 | 62 | team2.goals_scored += team_2_score; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `team2` is a `&` reference, so the data it refers to cannot be written
- 尝试改成可变引用后:
error[E0594]: cannot assign to `team2.goals_scored`, which is behind a `&` reference --> exercises/hashmaps/hashmaps3.rs:62:9 | 62 | team2.goals_scored += team_2_score; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `team2` is a `&` reference, so the data it refers to cannot be written | help: consider changing this to be a mutable reference | 61 | let team2 = &mut scores[&team_2_name]; | +++ error[E0594]: cannot assign to `team2.goals_conceded`, which is behind a `&` reference --> exercises/hashmaps/hashmaps3.rs:63:9 | 63 | team2.goals_conceded += team_1_score; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `team2` is a `&` reference, so the data it refers to cannot be written | help: consider changing this to be a mutable reference | 61 | let team2 = &mut scores[&team_2_name]; | +++
- 最终错误:
error[E0596]: cannot borrow data in an index of `HashMap<String, Team>` as mutable --> exercises/hashmaps/hashmaps3.rs:61:21 | 61 | let team2 = &mut scores[&team_2_name]; | ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable | = help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `HashMap<String, Team>` = help: to modify a `HashMap<String, Team>`, use `.get_mut()`, `.insert()` or the entry API
结论
你的初始疑问是正确的:
- Rust的可变方括号索引依赖
IndexMuttrait,而标准库中的HashMap<K, V>确实没有实现IndexMut。 - 原因在于
HashMap的方括号索引(map[key])在key不存在时会直接panic,这种设计在可变场景下并不安全也不灵活。标准库更推荐使用get_mut()(你第一种实现的方式)或者更高效的entry API来处理可变操作。
更简洁的entry API写法
scores.entry(team_1_name) .and_modify(|t| { t.goals_scored += team_1_score; t.goals_conceded += team_2_score; }) .or_insert(Team { goals_scored: team_1_score, goals_conceded: team_2_score, });
内容的提问来源于stack exchange,提问作者JustAnotherCoder894
相关产品推荐
相关产品推荐

