我正在尝试编写一些玩具代码,以在HashMap
中存储单词出现的次数。如果键存在,它会将计数器增加一,如果键不存在,则使用值1
添加它。我本能地想用模式匹配来做这件事,但我遇到了一个“借用可变”的错误:
fn read_file(name: &str) -> io::Result<HashMap<String, i32>> {
let b = BufReader::new(File::open(name)?);
let mut c = HashMap::new();
for line in b.lines() {
let line = line?;
for word in line.split(" ") {
match c.get_mut(word) {
Some(i) => {
*i += 1;
},
None => {
c.insert(word.to_string(), 1);
}
}
}
}
Ok(c)
}
我收到的错误是:
error[E0499]: cannot borrow `c` as mutable more than once at a time
--> <anon>:21:21
|
16 | match c.get_mut(word) {
| - first mutable borrow occurs here
...
21 | c.insert(word.to_string(), 1);
| ^ second mutable borrow occurs here
22 | }
23 | }
| - first borrow ends here
我理解为什么编译器会抱怨:我告诉它我要改变以 word
为键的值,但是插入操作并不在那个值上。然而,插入操作却在一个 None
上进行,所以我本以为编译器会意识到现在没有机会去改变 c[s]
。
我觉得这种方法应该可以工作,但我似乎缺少了一些窍门。我做错了什么?
编辑:我意识到我可以使用
if c.contains_key(word) {
if let Some(i) = c.get_mut(s) {
*i += 1;
}
} else {
c.insert(word.to_string(), 1);
}
但是与模式匹配相比,这段代码看起来非常丑陋(特别是必须将contains_key()
检查作为if语句进行,然后再次使用Some
进行检查)。
or_insert()
和or_insert_with()
提供了一种更简洁的实现方式。有关这些方法的信息,请参见A.B.的答案。 - Lukas Kalbertodt