哈希图中的借用和临时变量会引发循环错误

问题描述

我无法让一段代码工作,因为我得到的错误是循环的。

我从以下代码开始:

use std::collections::HashMap;

let mut hashm = HashMap::<Vec<&str>,&str>::new();
for i in v {
    let s = i.split('\t').collect::<Vec<&str>>();
    let j = s[0]
        .replace(&['{','}'][..],"") // replace multiple at once; https://users.rust-lang.org/t/24554/2
        .split(",")
        .collect::<Vec<&str>>();
    let k = s[1];
    hashm.insert(j,k);
}

我得到的错误s[0]

creates a temporary which is freed while still in use... 
hashm.insert(j,k);
             - borrow later used here

所以我将 hashm.insert(j,k) 更改为 hashm.insert(&j,k) 并将 HashMap::<Vec<&str>,&str>::new(); 更改为 HashMap::<&Vec<&str>,&str>::new();,但是我得到了同样的错误,以及这个:

hashm.insert(&j,k);
             ^^ borrowed value does not live long enough

我该如何纠正?

解决方法

let mut hashm = HashMap::<Vec<&str>,&str>::new();

您在此处指定的键和值类型是借用的。这意味着其他东西必须拥有键和值。这在某些情况下可以工作,但在这种情况下,您正在调用 str::replace,它返回一个 新分配的 String,然后由 split 借用。该字符串不能超过循环迭代——事实上,它在 let j 语句的末尾被释放。如果您将 String 分配给它自己的临时变量,它会持续足够长的时间以致于对 split 的调用会编译,但它仍会在循环结束时被释放,因此将其插入hashm 会失败。

如果您从 String 中生成 &str 作为键,则代码 will compile

use std::collections::HashMap;

let mut hashm = HashMap::<Vec<String>,&str>::new();
for i in v {
    let s = i.split('\t').collect::<Vec<&str>>();
    let j = s[0]
        .replace(&['{','}'][..],"")
        .split(",")
        .map(str::to_owned)
        .collect();
    let k = s[1];
    hashm.insert(j,k);
}

请注意,这个 HashMap 仍然不能超过 v,因为它的值仍然是借用的。如果这不是您想要的,那么您必须将其类型更改为 HashMap<Vec<String>,String> 并使用 hashm.insert(j,k.to_owned());