简体   繁体   English

在循环中插入哈希图

[英]Insert into hashmap in a loop

I'm opening a CSV file and reading it using BufReader and splitting each line into a vector.我正在打开一个 CSV 文件并使用BufReader读取它并将每一行拆分为一个向量。 Then I try to insert or update the count in a HashMap using a specific column as key.然后我尝试使用特定列作为键在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;
    }
}

The compiler kindly tells me s is shortlived.编译器好心地告诉我s是短暂的。 Storing from inside a loop a borrowed value to container in outer scope? 从循环内部将借用值存储到外部作用域中的容器? suggests "owning" the string, so I tried to change建议“拥有”字符串,所以我试图改变

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

to

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

but I get the error但我得到了错误

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

When I prepend ampersand ( & ) the error is当我在前面加上&符号( & )时,错误是

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

There is some deficiency in my Rust knowledge about borrowing.我对借用的 Rust 知识有一些不足。 How can I make the hashmap own the string passed as key?如何让哈希图拥有作为键传递的字符串?

The easiest way for this to work is for your map to own the keys.最简单的方法是让您的地图拥有密钥。 This means that you must change its type from HasMap<&str, i32> (which borrows the keys) to HashMap<String, i32> .这意味着您必须将其类型从HasMap<&str, i32> (借用键)更改为HashMap<String, i32> At which point you can call to_string to convert your tokens into owned strings:此时您可以调用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;
    }
}

Note however that this means that tokens[c] will be duplicated even if it was already present in the map.但是请注意,这意味着即使tokens[c]已经存在于地图中,它也会被复制。 You can avoid the extra duplication by trying to modify the counter with get_mut first, but this requires two lookups when the key is missing:您可以通过首先尝试使用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);
        }
    }
}

I don't know of a solution that would only copy the key when there was no previous entry but still do a single lookup.我不知道有什么解决方案只会在没有以前的条目时复制密钥但仍然进行单次查找。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM