繁体   English   中英

是否可以就地过滤矢量?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM