如何在 Rust 中迭代 Hashmap、打印键/值并删除值?

2024-02-07

对于任何语言来说,这都应该是一个微不足道的任务。这在 Rust 中不起作用。

use std::collections::HashMap;

fn do_it(map: &mut HashMap<String, String>) {
    for (key, value) in map {
        println!("{} / {}", key, value);
        map.remove(key);
    }
}

fn main() {}

这是编译器错误:

error[E0382]: use of moved value: `*map`
 --> src/main.rs:6:9
  |
4 |     for (key, value) in map {
  |                         --- value moved here
5 |         println!("{} / {}", key, value);
6 |         map.remove(key);
  |         ^^^ value used here after move
  |
  = note: move occurs because `map` has type `&mut std::collections::HashMap<std::string::String, std::string::String>`, which does not implement the `Copy` trait

为什么它试图移动引用?从文档来看,我认为移动/借用不适用于引用。


至少有两个原因不允许这样做:

  1. 您需要有两个并发的可变引用map— 由迭代器中使用的一个for循环和变量中的一map打电话map.remove.

  2. 您有对键和值的引用within尝试改变地图时的地图。如果允许您以任何方式修改地图,这些引用可能会失效,从而导致内存不安全。

Rust 的一个核心原则是别名 XOR 可变性。您可以对一个值有多个不可变引用,也可以对它有一个可变引用。

我不认为移动/借用适用于参考文献。

每种类型都遵循 Rust 的移动规则和可变别名。请让我们知道文档的哪一部分没有说明,以便我们解决这个问题。

为什么它试图移动引用?

这是由两部分组成的:

  1. 您只能有一个可变引用,因此可变引用不会实现Copy https://doc.rust-lang.org/std/marker/trait.Copy.html trait
  2. for loops 获取值并按值进行迭代 https://doc.rust-lang.org/std/iter/index.html#for-loops-and-intoiterator

你打电话时for (k, v) in map {},所有权map被转移到 for 循环,现在消失了。


我会执行地图的不可变借用(&*map)并迭代它。最后,我会把整个事情弄清楚:

fn do_it(map: &mut HashMap<String, String>) {
    for (key, value) in &*map {
        println!("{} / {}", key, value);
    }
    map.clear();
}

删除以字母“A”开头的键的每个值

I'd use HashMap::retain https://doc.rust-lang.org/std/collections/struct.HashMap.html#method.retain:

fn do_it(map: &mut HashMap<String, String>) {
    map.retain(|key, value| {
        println!("{} / {}", key, value);

        !key.starts_with("a")
    })
}

这保证了key and value当地图实际修改时不再存在,因此他们本来拥有的任何借用现在都消失了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 Rust 中迭代 Hashmap、打印键/值并删除值? 的相关文章

随机推荐