【问题标题】:Why does iterating over a HashMap<&str,&str> yield a &&str?为什么遍历 HashMap<&str,&str> 会产生 &&str?
【发布时间】:2016-10-22 12:11:44
【问题描述】:

我正在迭代 HashMap 并通过模式匹配将值放入一些本地变量中。

委托人

fn lyrics_no_bottles(song_template:&mut String){
    let mut template_partials = HashMap::new();

    template_partials.insert("start", "No more bottles");
    template_partials.insert("repeat", "no more bottles");
    template_partials.insert("remaining", "99 bottles");
    template_partials.insert("message", "Go to the store and buy some more");

    resolve_template(song_template, template_partials);
}

调用

fn resolve_template(song_template:&mut String, partials: HashMap<&str, &str>){
    let start:&str;
    let repeat:&str;
    let remaining:&str;
    let message:&str;

    for key in partials.keys(){
        match key {
            "start" => start = partials.get(key),
            "repeat" => repeat = partials.get(key),
            "remaining" => remaining = partials.get(key),
            "message" => message = partials.get(key)
        }
    }

    *song_template = song_template.replace("%1", start);
    *song_template = song_template.replace("%2", repeat);
    *song_template = song_template.replace("%3", message);
    *song_template = song_template.replace("%4", remaining);
}

错误输出

lib.rs:51:5: 58:6 error: type mismatch resolving `<std::collections::hash::map::Keys<'_, &str, &str> as core::iter::Iterator>::Item == &str`:
 expected &-ptr,
    found str [E0271]
lib.rs:51     for key in partials.keys(){
lib.rs:52         match key {
lib.rs:53             "start" => start = partials.get(key),
lib.rs:54             "repeat" => repeat = partials.get(key),
lib.rs:55             "remaining" => remaining = partials.get(key),
lib.rs:56             "message" => message = partials.get(key)
          ...
lib.rs:51:5: 58:6 help: run `rustc --explain E0271` to see a detailed explanation
lib.rs:53:32: 53:49 error: mismatched types:
 expected `&str`,
    found `core::option::Option<&&str>`
(expected &-ptr,
    found enum `core::option::Option`) [E0308]
lib.rs:53             "start" => start = partials.get(key),

当我将参数声明为HashMap&lt;&amp;str,&amp;str&gt; 时,我不明白为什么编译器认为存在&amp;&amp;str

【问题讨论】:

    标签: string hashmap pattern-matching rust


    【解决方案1】:

    因为that particular method returns a reference wrapped by an Option

    基本上,如果您将String 存储在那里并使用get .. 作为对get 的调用的结果,您将获得Option&lt;&amp;String&gt;。存储&amp;str 将返回Option&lt;&amp;&amp;str&gt; 作为调用get 的结果。

    值示例以及它们在您调用get 时的显示方式:

    String -> Option<&String>
    &str -> Option<&&str>
    u32 -> Option<&u32>
    

    当您将 &amp;str 作为值插入时,它的所有权将转移到哈希映射中。因此,哈希图使用 get ... 或 mutable references using get_mut 为您返回对它们的引用。

    操场目前已损坏(无法从中分享任何内容)......所以这是一个工作......您的代码的分解示例:

    use std::collections::HashMap;
    
    fn main() {
        let mut map: HashMap<&str, &str> = HashMap::new();
        map.insert("start", "value");
    
        let mut start: &str = "Unknown";
        let mut repeat: &str;
        let mut remaining: &str;
        let mut message: &str;
    
        for key in map.keys() {
            match &key[..] {
                "start" => start = map.get(key).unwrap(),
                "repeat" => repeat = map.get(key).unwrap(),
                "remaining" => remaining = map.get(key).unwrap(),
                "message" => message = map.get(key).unwrap(),
                _ => unreachable!()
            }
        }
    
        println!("Result: {}", start);
    }
    

    【讨论】:

    • 所以我还必须先销毁Option&lt;&amp;&amp;str&gt;,然后才能取消引用&amp;&amp;str ...我会尝试if let Some(x)
    • 正确。也许我也应该在我的回答中为您解决实际问题。我现在补充一下。
    • 谢谢你......如果让它使用,我无法使用它
    • 你能解释一下&amp;key[..]吗?
    • 哦,当然 - 对不起,它刚刚在我的脑海中出现(我在平板电脑上写了这个)。基本上你只想要一种方法来让你的匹配臂匹配相同的类型。您的key&amp;&amp;str.. 匹配武器是&amp;'static str。他们没有可比性。您可以使用任何您想要取消引用key 变量的方法。所以这些都可以工作:*key&amp;key[..]key.as_ref() 等。
    相关资源