我想遍历结构中的集合类型并删除一些值,但是Rust阻止我破坏集合:
fn some_method(&mut self) {
self.collection = self
.collection
.into_iter()
.filter(/* ... */
.collect();
}
我可以克隆所有值以构建另一个集合,但这效率不高。从Rust中适当的集合中删除值的惯用方式是什么?
into_iter
):#[derive(Debug)]
struct Scores {
collection: Vec<i32>,
}
impl Scores {
fn new() -> Scores {
return Scores {
collection: Vec::new(),
};
}
fn filter_in_above_50(&mut self) {
self.collection = self
.collection
.drain(..)
.filter(|score| score > &50)
.collect();
}
fn filter_in_above_50_using_into_iter(&mut self) {
let coll: &mut Vec<i32> = self.collection.as_mut();
let coll: Vec<i32> = coll
.into_iter()
.filter(|score| score > &&mut 50i32)
.map(|&mut x| x)
.collect();
self.collection = coll;
}
}
和测试:
#[test] fn score_test() { let mut s = Scores::new(); s.collection.push(199); s.collection.push(11); s.filter_in_above_50(); assert_eq!(s.collection, vec![199]); } #[test] fn score_test_using_into_iter() { let mut s = Scores::new(); s.collection.push(199); s.collection.push(11); s.filter_in_above_50_using_into_iter(); assert_eq!(s.collection, vec![199]); }
collection
是BTreeMap
且没有.drain()
或.retain
,并且可以在处理过程中清空树,所以要做的就是将树移出self.collection
,根据需要进行操作,然后放回去。 如您所见,Rust不允许通过简单的分配来实现这一点,因为如果在代码段运行期间出现紧急情况,self.collection
将会处于不一致状态。相反,您需要使用std::mem::replace
明确地执行此操作,该操作允许您通过提供可变内容来替代可变引用中的内容,从而使引用继续指向有效数据。
std::mem::replace