【问题标题】:Create a HashMap<i32, i32> in Rust在 Rust 中创建一个 HashMap<i32, i32>
【发布时间】:2017-01-02 22:51:08
【问题描述】:

在尝试使用 Rust 解决 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);
}

我想知道是否有更好的解决方案或最佳实践将 HashMaps 与原始类型一起使用?

【问题讨论】:

  • std::collections::HashMap::get 的签名说是,使用参考。
  • 注意:two_sum 采用 &amp;[i32] 参数更为惯用(因为它允许可能参数的严格超集)。

标签: rust


【解决方案1】:

如果你检查get方法的签名,你会发现:

  • 它接受一个以K: Borrow&lt;Q&gt;, Q: Hash + Eq为界的参数&amp;Q
  • 它返回Option&lt;&amp;V&gt;

因此,虽然哈希映射本身将包含原语,但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);
}

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

但是,这还不起作用,因为map.get(&amp;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 中的其他类型几乎没有区别。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-04-23
    • 2022-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多