Removing items from BTreeMap found using iteration

I would like to remove items from BTreeMap that were found using iteration.

As it is impossible to delete elements during iteration for obvious reasons, I put the elements in a vector. The main problem is that it is impossible to use a vector of links, but only a vector of values. All keys for which the record is to be deleted must be cloned (provided that the key implements the Clone attribute).

For example, this short sample does not compile:

 #![feature(drain)] use std::collections::BTreeMap; pub fn clean() { let mut map = BTreeMap::<String, i32>::new(); let mut to_delete = Vec::new(); { for (k, v) in map.iter() { if *v > 10 { to_delete.push(k); } } } for k in to_delete.drain(..) { map.remove(k); } } 

It generates the following compilation errors:

 src/lib.rs:21:9: 21:12 error: cannot borrow `map` as mutable because it is also borrowed as immutable [E0502] src/lib.rs:21 map.remove(k); ^~~ src/lib.rs:20:5: 22:6 note: in this expansion of for loop expansion src/lib.rs:12:23: 12:26 note: previous borrow of `map` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `map` until the borrow ends src/lib.rs:12 for (k, v) in map.iter() { ^~~ src/lib.rs:12:9: 16:10 note: in this expansion of for loop expansion src/lib.rs:24:2: 24:2 note: previous borrow ends here src/lib.rs:4 pub fn clean() { ... src/lib.rs:24 } 

Changing to_delete.push(k) with to_delete.push(k.clone()) makes this snippet correctly compiled. But, then it is quite expensive if each key to delete must be cloned.

Is there a better solution?

 $ rustc --version rustc 1.5.0-nightly (65d5c0833 2015-09-29) 
+5
source share
1 answer

I would probably look at the problem from a slightly different direction. Instead of trying to save the map, I would just create a completely new one:

 use std::collections::BTreeMap; pub fn main() { let mut map = BTreeMap::new(); map.insert("thief", 5); map.insert("troll", 52); map.insert("gnome", 7); let map: BTreeMap<_, _> = map.into_iter() .filter(|&(_, v)| v <= 10) .collect(); println!("{:?}", map); // troll is gone } 
+1
source

Source: https://habr.com/ru/post/1232827/


All Articles