在循环中插入到hashmap中



我正在打开一个CSV文件,并使用BufReader读取它,并将每一行拆分为一个向量。然后,我尝试使用特定列作为键在HashMap中插入或更新计数。

let mut map: HashMap<&str, i32> = HashMap::new();
let reader = BufReader::new(input_file);
for line in reader.lines() {
let s = line.unwrap().to_string();
let tokens: Vec<&str> = s.split(&d).collect(); // <-- `s` does not live long enough
if tokens.len() > c {
println!("{}", tokens[c]);
let count = map.entry(tokens[c].to_string()).or_insert(0);
*count += 1;
}
}

编译人员善意地告诉我s是短命的。是否从循环内部将借用的值存储到外部作用域中的容器?建议"拥有"字符串,所以我尝试更改

let count = map.entry(tokens[c]).or_insert(0);

let count = map.entry(tokens[c].to_string()).or_insert(0);

但是我得到错误

expected `&str`, found struct `std::string::String`
help: consider borrowing here: `&tokens[c].to_string()`

当我准备安培数(&(时,错误为

creates a temporary which is freed while still in use
note: consider using a `let` binding to create a longer lived

我对借款的了解有些不足。如何使hashmap拥有作为关键字传递的字符串?

实现这一点的最简单方法是让映射拥有密钥。这意味着您必须将其类型从HasMap<&str, i32>(借用密钥(更改为HashMap<String, i32>。此时,您可以调用to_string将您的代币转换为拥有的字符串:

let mut map: HashMap<String, i32> = HashMap::new();
let reader = BufReader::new(input_file);
for line in reader.lines() {
let s = line.unwrap().to_string();
let tokens:Vec<&str> = s.split(&d).collect();
if tokens.len() > c {
println!("{}", tokens[c]);
let count = map.entry(tokens[c].to_string()).or_insert(0);
*count += 1;
}
}

然而,请注意,这意味着tokens[c]将被复制,即使它已经存在于映射中。您可以通过尝试首先使用get_mut修改计数器来避免额外的重复,但当密钥丢失时,这需要两个查找:

let mut map: HashMap<String, i32> = HashMap::new();
let reader = BufReader::new(input_file);
for line in reader.lines() {
let s = line.unwrap().to_string();
let tokens:Vec<&str> = s.split(&d).collect();
if tokens.len() > c {
println!("{}", tokens[c]);
if let Some (count) = map.get_mut (tokens[c]) {
*count += 1;
} else {
map.insert (tokens[c].to_string(), 1);
}
}
}

我不知道有什么解决方案可以只在没有以前的条目时复制密钥,但仍然进行一次查找。

最新更新