问题描述
我从以下代码开始:
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());
。