2017-01-02 4 views
1

Während ein LeetCode Problem mit Rost zu lösen versuchen, traf ich ein seltsames Problem: es sieht aus wie ich keine HashMap mit primitiven Typen erstellen:erstellen HashMap <i32, i32> in Rust

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

Der Compiler beschwert sich:

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 `&_` 

Ist es notwendig, immer Bezug mit HashMap in Rust verwenden?

EDIT:

Sieht aus wie es notwendig ist ... Die Lösung ein bisschen hässlich, aber Werke sieht sowieso.

Ich frage mich, ob es eine bessere Lösung oder einige beste Praxis gibt, HashMaps mit primitiven Typen zu verwenden?

+0

Die Signatur [std :: Sammlungen :: HashMap :: get] (https://doc.rust-lang.org/stable/std/collections/struct.HashMap.html#method.get) sagt ja , verwende eine Referenz. – ljedrz

+0

Hinweis: Es ist idiomatischer für 'two_sum', ein' & [i32] 'Argument zu nehmen (da es eine strikte Obermenge möglicher Argumente zulässt). –

Antwort

6

Wenn Sie die Signatur der get Methode zu überprüfen, werden Sie feststellen, dass:

  • es ein Argument &Q begrenzt durch K: Borrow<Q>, Q: Hash + Eq
  • Option<&V>

es gibt also während der Hash akzeptiert Karte selbst enthält Primitive, die Schnittstelle von get erfordert eine Referenz und gibt eine Referenz zurück.

Das bedeutet:

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

Wo I (1) einen Verweis auf get passieren und (2) dereferenzieren das Ergebnis, das ich bekommen (und wandeln sie von i32 zu usize).

Allerdings bedeutet dies noch nicht arbeiten, weil map.get(&a) die map für die Dauer des map Block leiht, so kann man nicht auch hinein einfügen. Dies wiederum wird erreicht, indem das Einsetzen nach dem match Block gelöst:

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

Das ist es. Hashmap mit Primitivtypen.

Seitennotiz: Im Gegensatz zu einigen anderen Sprachen sind primitive Typen in Rust kaum von anderen Typen zu unterscheiden.

Verwandte Themen