2017-01-02 13 views
1

錆と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); 
} 

コンパイラは文句を言う:私はプリミティブ型を持つHashMapを作成することはできませんように見えます:

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で常に参照を使用する必要がありますか?

EDIT:それは必要であるように

が見える...解決策は少し醜いとにかく動作します。

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を使用する方が良い解決法やベストプラクティスがあるのだろうか?

+0

[std :: collections :: HashMap :: get](https://doc.rust-lang.org/stable/std/collections/struct.HashMap.html#method.get)のシグネチャは、「はい」と表示されます。 、参照を使用します。 – ljedrz

+0

注: 'two_sum'が'&[i32] '引数を取るのはもっと慣れています(可能な引数の厳密なスーパーセットが許されるので)。 –

答えて

6

あなたがgetメソッドのシグネチャをチェックすると、あなたはそれを実現します。

  • それはハッシュながらK: Borrow<Q>, Q: Hash + Eq
  • で囲まれた引数&Qが、それは、そうOption<&V>

を返す受け入れマップ自体にはプリミティブが含まれますが、のインターフェイスにはgetが必要で、参照が必要です。

これが意味:I(1)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); 
} 

(2)Iを取得(及びi32からusizeに変換)結果間接参照。 map.get(&a)mapブロックの期間mapを借りるので、あなたががそれに挿入することはできませんので

しかし、これはまだ、動作しません。

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); 
} 

それだ:ターンでこれがmatchブロックの後に挿入を移動することによって解決されます。プリミティブタイプのHashmap

他の言語とは異なり、プリミティブ型は、Rustの他の型と区別がつきません。