Rust中的“类型可变性不同”

8
我尝试从一个向量中删除指定元素(如果该元素存在):
use std::collections::HashMap;

fn test(map: HashMap<String, Vec<String>>, department: String, employee: String) {
    let &mut list = map.get(&department).unwrap();
    let index = list.iter().position(|x| x == &employee);
    match index {
        Some(i) => {
            list.remove(i);
        },
        None => {
            println!("No records of {} in {}!", &employee, &department);
        },
    }
}

我遇到了这个错误:

error[E0308]: mismatched types
 --> src/lib.rs:4:9
  |
4 |     let &mut list = map.get(&department).unwrap();
  |         ^^^^^^^^^   ----------------------------- this expression has type `&std::vec::Vec<std::string::String>`
  |         |
  |         types differ in mutability
  |
  = note:      expected reference `&std::vec::Vec<std::string::String>`
          found mutable reference `&mut _`

游乐场

我以为我理解了错误提示的含义(第170行右侧返回一个不可变的向量引用),但我不确定该如何解决它。如果尝试像这样做:

let mut list = map.get(&department).unwrap();
let index = list.iter().position(|x| x == &employee);
match index {
    Some(i) => {
        list.remove(i);
    },
    ...
}

我接着得到:

error[E0596]: cannot borrow `*list` as mutable, as it is behind a `&` reference
 --> src/lib.rs:8:13
  |
4 |     let mut list = map.get(&department).unwrap();
  |         -------- help: consider changing this to be a mutable reference: `&mut std::vec::Vec<std::string::String>`
...
8 |             list.remove(i);
  |             ^^^^ `list` is a `&` reference, so the data it refers to cannot be borrowed as mutable

游乐场

对我来说,这些错误似乎有些循环,这让我觉得需要重新思考我的设计。 我该如何解决此问题?

1个回答

7
get 方法会返回一个不可变的 Option<&V>,该选项不允许调用 .remove(i)。使用get_mut 方法可以获得可变的Option<&mut V>。调用它需要对映射本身进行可变操作,这表明我们正在做正确的事情。
use std::collections::HashMap;

fn test(map: &mut HashMap<String, Vec<String>>, department: String, employee: String) {
    //       ^^^^ 
    let list = map.get_mut(&department).unwrap();
    //             ^^^^^^^
    let index = list.iter().position(|x| x == &employee);
    match index {
        Some(i) => {
            list.remove(i);
        },
        None => {
            println!("No records of {} in {}!", &employee, &department);
        },
    }
}

游乐场


1
@cloudy_eclispse注意,您可以使用Vec :: retain来简化position /remove的过程。 请参见根据某些条件从Vec中删除元素 - trent
@trentcl:现在仔细查看retain(),虽然这对于删除元素来说很好,但我希望能保留如果结果为none时我将显示的错误消息。有没有一种简洁的方法可以做到这一点? - cloudy_eclispse
@cloudy_eclispse 很遗憾,这不是一件容易的事情。你可以在夜间版本中使用 drain_filter(如果它返回任何项,则它们已被删除;否则,请打印消息),但在稳定版本中,这个答案可能是你最好的选择。 - trent

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接