在 Rust 中创建 HashMap<i32、i32>



在尝试解决leetcode问题时,我遇到了一个奇怪的问题:看来我无法创建具有原始类型的HashMap

use std::collections::HashMap;
fn two_sum(nums: &Vec<i32>, target: i32) -> (usize, usize) {
    let mut map = HashMap::new();
    for (i, x) in nums.iter().enumerate() {
        match map.get(target - x) {
            Some(k) => return (k, i),
            None => map.insert(x, i)
        };
    }
    return (0, 0);
}
fn main() {
    let ret = two_sum(&vec![1,2,3], 4);
    println!("{}, {}", ret.0, ret.1);
}

编译器抱怨:

error[E0308]: mismatched types
 --> two_sum.rs:6:23
  |
6 |         match map.get(target - x) {
  |                       ^^^^^^^^^^ expected reference, found i32
  |
  = note: expected type `&_`
  = note:    found type `i32`
error[E0308]: mismatched types
 --> two_sum.rs:7:32
  |
7 |             Some(k) => return (k, i),
  |                                ^ expected usize, found reference
  |
  = note: expected type `usize`
  = note:    found type `&_`

是否有必要始终使用rust中的hashmap使用参考?

编辑:

看来是必要的...解决方案看起来有些丑陋,但无论如何都可以。

use std::collections::HashMap;
fn two_sum(nums: &[i32], target: i32) -> (usize, usize) {
    let mut map = HashMap::new();
    for (i, x) in nums.iter().enumerate() {
        let df = target - x;
        if map.contains_key(&df) {
            return (*map.get(&df).unwrap(), i);
        }
        map.insert(x, i);
    }
    return (0, 0);
}
fn main() {
    let ret = two_sum(&vec![1,2,3], 4);
    println!("{}, {}", ret.0, ret.1);
}

我想知道是否有更好的解决方案或使用原始类型的标志性的一些最佳实践?

如果您检查get方法的签名,您将意识到:

  • 它接受一个由K: Borrow<Q>, Q: Hash + Eq界限的参数&Q
  • 它返回Option<&V>

因此,虽然哈希地图本身将包含原始图,但是 get接口需要参考并返回参考。

这意味着:

fn two_sum(nums: &Vec<i32>, target: i32) -> (usize, usize) {
    let mut map = HashMap::new();
    for (i, x) in nums.iter().enumerate() {
        match map.get(&(target - x)) {
            //        ^~~~~~~~~~~~~
            Some(k) => return (*k as usize, i),
            //                 ^~~~~~~~~~~
            None => map.insert(x, i)
        };
    }
    return (0, 0);
}

其中i(1)将引用到get和(2)取消我获得的结果(并将其从i32转换为usize)。

但是,这尚未起作用,因为map.get(&a)map块的持续时间内借用了map,因此您不能 插入其中。依次通过在match块之后移动插入来解决这一点:

fn two_sum(nums: &Vec<i32>, target: i32) -> (usize, usize) {
    let mut map = HashMap::new();
    for (i, x) in nums.iter().enumerate() {
            let a = target - x;
            match map.get(&a) {
                Some(k) => return (*k as usize, i),
                None => (),
            };
            map.insert(x, i);
    }
    return (0, 0);
}

就是这样。 Hashmap具有原始类型。

旁注:与其他一些语言不同,原始类型与Rust中的其他类型都无法区分。

最新更新