簡體   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