Ideally I'd like to do this all efficiently, without needing to clone things.
Here's a concrete example of what I'm trying to do.
First I have a list of of file paths:
test/
test/a
test/b
test/b/1
test/b/2
test/b/3
Modeled like this:
let mut items = vec![vec!["test"], vec!["test", "a"], vec!["test", "b"], vec!["test", "b", "1"], vec!["test", "b", "2"], vec!["test", "b", "3"]];
I would like to sort this list of paths by the number of items contained in the parent folder of each path item. So first I need to calculate the number of items in each "folder", I store those results in a map like this:
for each in items.iter() {
let parent = &each[0..each.len() - 1];
*map.entry(parent).or_insert(0) += 1;
}
And the resulting map looks like:
{
[]: 1,
["test"]: 2,
["test", "b"]: 3
}
Next I want to use this map to sort the collection of items. I'm trying to do that like this:
items.sort_unstable_by(|a, b| {
let a_parent = &a[0..a.len() - 1];
let b_parent = &b[0..b.len() - 1];
map.get(a_parent).unwrap_or(&0).cmp(&map.get(b_parent).unwrap_or(&0))
});
But when I try that I'm running into borrowing problems saying "cannot borrow items
as mutable because it is also borrowed as immutable". I think I generally understand why rust is complaining. But I also generally think that in this case the code is OK, I want to know how to get rust to also think that it's OK.
Here's full (non-working) code:
use std::collections::HashMap;
fn main() {
let mut items = vec![vec!["test"], vec!["test", "a"], vec!["test", "b"], vec!["test", "b", "1"], vec!["test", "b", "2"], vec!["test", "b", "3"]];
let mut map: HashMap<&[&str], usize> = HashMap::new();
for each in items.iter() {
let parent = &each[0..each.len() - 1];
*map.entry(parent).or_insert(0) += 1;
}
items.sort_unstable_by(|a, b| {
let a_parent = &a[0..a.len() - 1];
let b_parent = &b[0..b.len() - 1];
map.get(a_parent).unwrap_or(&0).cmp(&map.get(b_parent).unwrap_or(&0))
});
println!("{:?}", items);
println!("{:?}", map);
}
Errors:
Compiling playground v0.0.1 (file:///playground)
warning: unused import: `std::cmp::Ordering`
--> src/main.rs:2:9
|
2 | use std::cmp::Ordering;
| ^^^^^^^^^^^^^^^^^^
|
= note: #[warn(unused_imports)] on by default
error[E0502]: cannot borrow `items` as mutable because it is also borrowed as immutable
--> src/main.rs:13:9
|
8 | for each in items.iter() {
| ----- immutable borrow occurs here
...
13 | items.sort_unstable_by(|a, b| {
| ^^^^^ mutable borrow occurs here
...
21 | }
| - immutable borrow ends here
error: aborting due to previous error
For more information about this error, try `rustc --explain E0502`.
error: Could not compile `playground`.
To learn more, run the command again with --verbose.