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