循环插入hashmap

Insert into hashmap in a loop

我正在打开一个 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 是短暂的。 Storing from inside a loop a borrowed value to container in outer scope? 建议 "owning" 字符串,所以我尝试更改

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

我对借用的Rust知识有一些不足。如何让散列映射拥有作为键传递的字符串?

最简单的方法是让您的地图拥有密钥。这意味着您必须将其类型从 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);
        }
    }
}

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