对 hashmaps3.rs 感到困惑

问题描述 投票:0回答:1

我正在做沙沙声练习,在完成其中一项练习后我得到了一个简单的问题,但我也不确定我没有做错其他事情。

问题是: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
        });
    }
}

但是,这不能编译。答案可能是方括号表示法,它似乎是

index
的语法糖,不会返回可变的,但我想检查这是否正确。

if ! scores.contains_key(&team_2_name) {
    scores.insert(team_2_name.clone(), Team { goals_conceded: 0, goals_scored: 0 });
}

let team2 = scores[&team_2_name];
team2.goals_scored   += team_2_score;
team2.goals_conceded += team_1_score;

我试图让编译器来教我。我知道

let team2...
行是错误的,因为它不是可变的,但我认为编译器可能会给我一个很好的提示。

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];
   |             +++

这让我很感动:

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 hashmap rust-rustlings
1个回答
0
投票

Rust 支持两种使用

[]
进行索引的方式(特征):

Index 返回一个不可变的引用 - 如果只想阅读内容,则很有用。

IndexMut 返回一个可变引用 - 如果想要更改某个索引处的内容,则很有用。

HashMap
没有实现
IndexMut
,可能是因为索引合约(如果条目不存在则出现恐慌)会导致误解和糟糕的解决方法。

HashMap
改为提供
get_mut
entry

© www.soinside.com 2019 - 2024. All rights reserved.