Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

String-keyed HashMap in rust?

Tags:

hashmap

rust

I'm having trouble figuring out how to use a HashMap with a key of type ~str idiomatically. For example,

let mut map: hashmap::HashMap<~str, int> = hashmap::HashMap::new();
// Inserting is fine, I just have to copy the string.
map.insert("hello".to_str(), 1);

// If I look something up, do I really need to copy the string?
// This works:
map.contains_key(&"hello".to_str());

// This doesn't: as expected, I get
// error: mismatched types: expected `&~str` but found `&'static str` (expected &-ptr but found &'static str)
map.contains_key("hello");

Based on this bug report, I tried

map.contains_key_equiv("hello");

but got

error: mismatched types: expected `&<V367>` but found `&'static str` (expected &-ptr but found &'static str)

I really don't understand this last message; does anyone have a suggestion?

like image 713
Joe Neeman Avatar asked Jul 28 '13 21:07

Joe Neeman


1 Answers

You have HashMap<K, V> with ~str (an owned string) as K; thus, where it wants &K for things, that is &~str—a reference to an owned string. You, however, are passing it a reference to a static string (a string literal without any sigil [&, ~, etc.], "hello", is of type &'static str).

For string literals, do not use .to_str(); instead, prefix it with a ~, as ~"hello". A string literal like that is of type ~str. For a non-literal, you should typically use .to_owned() of a &str.

The eventual code can operate like this:

use std::hashmap::HashMap;

fn main() {
    let mut h = HashMap::new::<~str, int>();
    h.insert(~"foo", 42);
    printfln!("%?", h.find(&~"foo")); // => Some(&42)
    printfln!("%?", h.contains_key(&~"foo")); // => true

    // You don’t actually need the HashMap to own the keys (but
    // unless all keys are 'static, this will be likely to lead
    // to problems, so I don’t suggest you do it in reality)
    let mut h = HashMap::new::<&str, int>();
    h.insert("foo", 42);
    printfln!("%?", h.find(& &"foo")); // => Some(&42)
}

Observe that when you need a reference to a reference you can't do && as that is the boolean AND operator; you need to do &(&x) or & &x.

(Note also that any issue from three months ago may not be current; I'm not certain of the current state of HashMap's comparison techniques—try both ways, with the correct types.)

like image 88
Chris Morgan Avatar answered Nov 15 '22 02:11

Chris Morgan