You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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
        });
    }
}

第二种(编译失败的尝试过程)

最初尝试用方括号索引修改,遇到一系列错误:

  1. 首次错误:
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];
   |             +++
  1. 按提示添加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];
   |                         +
  1. 改成引用后:
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
  1. 尝试改成可变引用后:
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];
   |                      +++
  1. 最终错误:
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的可变方括号索引依赖IndexMut trait,而标准库中的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 20:34:52