为什么迭代 HashMap<&str,&str> 会产生 &&str?

xet*_*a11 2 string hashmap pattern-matching rust

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

委托人

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);
}
Run Code Online (Sandbox Code Playgroud)

被称为

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);
}
Run Code Online (Sandbox Code Playgroud)

错误输出

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),
Run Code Online (Sandbox Code Playgroud)

我不明白为什么编译器认为&&str当我将参数声明为HashMap<&str,&str>.

Sim*_*ead 8

因为该特定方法返回一个由 Option 包装的引用

基本上,如果您String在那里存储 a 并使用get.. 您将得到一个Option<&String>作为调用 .. 的结果get。存储&str将返回一个Option<&&str>,作为调用的结果get

值的示例以及它们在您致电时如何显示get

String -> Option<&String>
&str -> Option<&&str>
u32 -> Option<&u32>
Run Code Online (Sandbox Code Playgroud)

&str当您将其作为值插入时,其所有权将被转移到哈希图。因此,hashmap 使用get... 返回对它们的引用,或使用 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);
}
Run Code Online (Sandbox Code Playgroud)

  • 哦,当然 - 抱歉,它刚刚在我的脑海中浮现(我在火车上用平板电脑写下了这个)。基本上你只需要一种方法来让你的匹配臂匹配相同的类型。你的“key”是“&amp;&amp;str”..而匹配臂是“&amp;'static str”。他们没有可比性。您可以使用任何想要取消引用“key”变量的方法。所以这些都可以工作:`*key`、`&amp;key[..]`、`key.as_ref()` 等。 (4认同)