Rust中的字符串键HashMap?

7

我在如何使用键类型为~str的HashMap方面遇到了困难。例如,

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

根据这个错误报告,我尝试了以下操作:

map.contains_key_equiv("hello");

但是收到了
error: mismatched types: expected `&<V367>` but found `&'static str` (expected &-ptr but found &'static str)

我真的不理解这个最后的消息;有人有建议吗?

这个问题现在已经过时了;由于Borrow特质的存在,将代码简单地转换为当前的语法和方法名称就可以正常工作,而且没有错误。 - Chris Morgan
2个回答

4
你有一个 HashMap<K, V>,其中 K 是一个拥有的字符串 (~str),因此在需要 &K 用于 things 时,它实际上需要的是对拥有的字符串的引用 &~str。然而,你正在将其传递给一个静态字符串 (没有任何标记 [&~ 等]) 的引用,如 "hello",它是一个 &'static str 类型。
对于字符串字面量,不要使用 .to_str();相反,使用前缀 ~,如 ~"hello"。这样的字符串字面量是 ~str 类型。对于非字面量,通常应该使用 &str.to_owned()
最终的代码可以像这样运行:
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)
}

请注意,当你需要引用一个引用时,你不能使用 &&,因为那是布尔运算符;你需要使用 &(&x) 或者 & &x
(还要注意,任何三个月前的问题可能已经不再当前;我不确定HashMap的比较技术的当前状态 - 请尝试两种方式,使用正确的类型。)

随着 Rust 1.0 的发布,这已经不再准确了。 - Greg
是的。HashMap API现在更好用了,因为getcontains_key可以接受与键类型等效的类型,这要归功于Borrow,所以你只需要使用h.get("foo")而不是旧的h.find(&~"foo"),后者执行了不必要的堆分配。https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=0899b611008ea9792aa653e882835c44 是代码示例的更新,使用了当前的技术。然而,我不太愿意整体更新答案,因为这是一个在当前Rust中根本不相关的问题,多亏了这个Borrow特性。 - Chris Morgan

3

contains_key_equiv的声明如下:

pub fn contains_key_equiv<Q:Hash + Equiv<K>>(&self, key: &Q) -> bool

那就是,它需要引用一些等同于“K == ~str”的东西。因此,为了检查一个&str(与~str等价),我们需要一个& &str(指向字符串切片的引用)。
map.contains_key_equiv(&("hello"));

// or

map.contains_key_equiv(& &"hello");

(请注意,这些是等效的,并且只是为了绕过“foo”==&“foo”都是&str的事实)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接