问题
I'm attempting to count the character frequency in a string and store the count of each character in a BTreeMap
. However, I'm getting a warning and would like to get rid of it.
This is what I've tried:
use std::collections::BTreeMap;
fn letter_frequency(input: &str) -> BTreeMap<char, i32> {
let mut tree: BTreeMap<char, i32> = BTreeMap::new();
for item in &input.chars().collect::<Vec<char>>() {
match tree.get(item) {
Some(count) => tree.insert(*item, *count + 1),
None => tree.insert(*item, 1)
};
}
tree
}
This is the warning:
warning: cannot borrow `tree` as mutable because it is also borrowed as immutable
--> src/lib.rs:7:28
|
6 | match tree.get(item) {
| ---- immutable borrow occurs here
7 | Some(count) => tree.insert(*item, *count + 1),
| ^^^^ ------ immutable borrow later used here
| |
| mutable borrow occurs here
|
= note: #[warn(mutable_borrow_reservation_conflict)] on by default
= warning: this borrowing pattern was not meant to be accepted, and may become a hard error in the future
= note: for more information, see issue #59159 <https://github.com/rust-lang/rust/issues/59159>
How do I correctly use match
with a BTreeMap
to avoid the error ?
回答1:
Like Svetlin mentions in a comment, the entry API is your friend. Below I've also removed one unneeded collect.
fn letter_frequency(input: &str) -> BTreeMap<char, i32> {
let mut tree = BTreeMap::new();
for item in input.chars() {
let count = tree.entry(item).or_insert(0);
*count += 1;
}
tree
}
The temporary variable count is not really needed: *tree.entry(item).or_insert(0) += 1;
works just fine but might look a bit crowded at first.
来源:https://stackoverflow.com/questions/59347094/cannot-borrow-as-mutable-because-it-is-also-borrowed-as-immutable-with-match