Rust:两个哈希图的简单同时迭代,无需压缩

我试图用一个键同时循环遍历两个地图,而不调用 zip()。我似乎无法让以下代码工作。我究竟做错了什么?

main.rs

use std::collections::HashMap;

mod iteratemaps;

fn main() {
    let mut m1 = HashMap::new();
    m1.insert(0, 10);
    m1.insert(1, 11);
    m1.insert(2, 12);

    let mut m2 = HashMap::new();
    m2.insert(0, 20);
    m2.insert(1, 21);
    m2.insert(2, 22);

    iteratemaps::iterate_maps(&m1, &m2);
}

iteratemaps.rs

use std::collections::HashMap;

pub fn iterate_maps(
    m1: &HashMap<u32, i32>,
    m2: &HashMap<u32, i32>,
) {
    // doesn't work
    for i in 0..m1.len() {
        println!("{:?}, {:?}", m1.get(&i), m2.get(&i));
    }

    // works
    // for (k, e1) in m1.iter() {
    //     let mut e2 = m2.get(k);
    //     println!("{:?}, {:?}", e1, e2)
    // }
}

我得到的错误是:

9 |         println!("{:?}, {:?}", m1.get(&i), m2.get(&i));
  |                                       ^^ expected `u32`, found `usize

回答

您可以像评论中提到的那样强制i转换u32为,但更强大的解决方案是迭代其中一个哈希映射的。这样做的优点是不仅可以自动提供正确的类型(它甚至将是一个引用,这是您需要传递给 的HashMap::get),而且即使您远离连续的整数键,它也能工作。例如:

pub fn iterate_maps(m1: &HashMap<u32, i32>, m2: &HashMap<u32, i32>) {
    for k in m1.keys() {
        println!("{:?}, {:?}", m1.get(k), m2.get(k));
    }
}

您可以通过迭代第一个哈希映射的键和值来避免不必要的哈希表查找,并且只查找第二个中的键:

pub fn iterate_maps(m1: &HashMap<u32, i32>, m2: &HashMap<u32, i32>) {
    for (k, v1) in m1 {
        let v2 = m2.get(k);
        println!("{:?}, {:?}", v1, v2);
    }
}

在处理这段代码时,我想到了一个额外的改进:它可以在两个哈希图中的键和值上返回一个迭代器,以便调用者决定如何使用这些值。(您可以将迭代器视为zip实际适用于您的用例的 的变体。)同时,我们可以使函数在键和值类型上通用,以便它适用于任何类型的哈希图。结果如下所示:

pub fn iterate_maps<'a: 'b, 'b, K: Eq + Hash, V>(
    m1: &'a HashMap<K, V>,
    m2: &'b HashMap<K, V>,
) -> impl Iterator<Item = (&'a K, &'a V, &'b V)> {
    m1.iter().map(move |(k, v1)| (k, v1, m2.get(k).unwrap()))
}

// later, in main:
for (_k, v1, v2) in iteratemaps::iterate_maps(&m1, &m2) {
    println!("{:?}, {:?}", v1, v2);
}

最后,一个不相关的注意事项:在 Rust 中,您可以使用mod modname { ... block ...}语法指定一个内联模块。这将允许您提供整个代码在一个问题中片断,如图所示这里。


以上是Rust:两个哈希图的简单同时迭代,无需压缩的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>