[英]is it possible to filter on a vector in-place?
我想从Vec
中删除一些元素,但是vec.iter().filter().collect()
会创建一个包含借用项目的新向量。
我想在没有额外 memory 分配的情况下改变原始Vec
(并保留 memory 的已删除元素作为向量的额外容量)。
如果要删除元素,可以使用retain()
,如果闭包返回false
则从向量中删除元素:
let mut vec = vec![1, 2, 3, 4];
vec.retain(|&x| x % 2 == 0);
assert_eq!(vec, [2, 4]);
如果要修改元素,则必须for x in vec.iter_mut()
中的for x in vec.iter_mut()
。
如果你真的想在过滤它时改变矢量的元素,你可以使用仅限夜间的方法Vec::drain_filter
,这是一个非常灵活的工具:
#![feature(drain_filter)]
fn main() {
let mut vec = vec![1, 2, 3, 4];
vec.drain_filter(|x| {
if *x % 2 == 0 {
true
} else {
*x += 100;
false
}
});
assert_eq!(vec, [101, 103]);
}
它还允许您获取已删除的元素,因为整个方法的返回值是迭代器!
直到Vec::drain_filter
稳定下来,我们可以用 homebrewed rust 解决这个问题:
fn main() {
let mut v = vec![1, 2, 3, 4];
let mut i = 0;
while i < v.len() {
if v[i] % 2 == 0 {
v.remove(i);
} else {
v[i] += 100;
i += 1;
}
}
println!("{:?}", v); // [101, 103]
}
顺便说一句, remove()
是一个O(n)
操作,但不分配 memory。
操场
我提供了我对这个问题的看法,因为我不知道保留方法:
impl<T> RemoveFilter<T> for Vec<T> {}
pub trait RemoveFilter<T>: BorrowMut<Vec<T>> {
fn remove_filter<F: for<'b> FnMut(&'b T) -> bool>(&mut self, mut cb: F) {
let vec: &mut Vec<T> = self.borrow_mut();
let mut write_to = 0;
let mut read_from = 0;
while read_from < vec.len() {
let maintain = cb(&mut vec[read_from]);
if maintain {
vec.as_mut_slice().swap(read_from, write_to);
write_to += 1;
}
read_from += 1;
}
vec.resize_with(write_to, || panic!("We are shrinking the vector"));
}
}
它会在迭代时移动元素,然后删除任何遗留的元素。 我认为这是代码,可以很容易地修改以解决其他问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.