有没有办法根据谓词排出向量的一部分?
Is there a way to drain parts of a vector based on a predicate?
我正在尝试根据谓词从向量中删除一些元素,然后收集结果。这是一个具有预期结果的(无效)示例:
let mut v: Vec<i32> = vec![1, 2, 3, 4, 5, 6];
let drained: Vec<i32> = v.iter().filter(|e| (*e) % 2 == 0).drain(..).collect();
assert_eq!(v, vec![1, 3, 5]);
assert_eq!(drained, vec![2, 4, 6]);
这会导致错误
error[E0599]: no method named `drain` found for type `std::iter::Filter<std::slice::Iter<'_, i32>, [closure@src/main.rs:4:45: 4:62]>` in the current scope
--> src/main.rs:4:64
|
4 | let drained: Vec<i32> = v.iter().filter(|e| (*e) % 2 == 0).drain(..).collect();
| ^^^^^
我查看了几个备选方案,none 其中似乎符合我的要求:
Vec::retain
从向量中删除元素,但不归还已删除元素的所有权。
v.drain(..).filter(condition).collect()
returns drained
的正确值,但清空了整个向量。
不在稳定的 Rust 1.33.0 中。有一个名为 drain_filter
的不稳定的夜间功能完全符合您的要求:
#![feature(drain_filter)]
fn main() {
let mut v: Vec<i32> = vec![1, 2, 3, 4, 5, 6];
let drained: Vec<i32> = v.drain_filter(|&mut e| e % 2 == 0).collect();
assert_eq!(v, vec![1, 3, 5]);
assert_eq!(drained, vec![2, 4, 6]);
}
作为稳定的解决方法,您可以使用 Iterator::partition
,但它不会重复使用内存:
fn main() {
let v: Vec<i32> = vec![1, 2, 3, 4, 5, 6];
let (drained, v): (Vec<_>, Vec<_>) = v.into_iter().partition(|&e| e % 2 == 0);
assert_eq!(v, vec![1, 3, 5]);
assert_eq!(drained, vec![2, 4, 6]);
}
文档指出 Vec.retain 将操作 in-place,并按顺序访问每个元素,恰好一次。
fn drain_where<T, Pred : Fn(&T) -> bool>(source: &mut Vec<T>, pred: Pred) -> Vec<T>
where T : Copy {
let mut drained: Vec<T> = Vec::new();
source.retain(|item| {
if pred(item) { drained.push(*item); false } else { true }
});
drained
}
我正在尝试根据谓词从向量中删除一些元素,然后收集结果。这是一个具有预期结果的(无效)示例:
let mut v: Vec<i32> = vec![1, 2, 3, 4, 5, 6];
let drained: Vec<i32> = v.iter().filter(|e| (*e) % 2 == 0).drain(..).collect();
assert_eq!(v, vec![1, 3, 5]);
assert_eq!(drained, vec![2, 4, 6]);
这会导致错误
error[E0599]: no method named `drain` found for type `std::iter::Filter<std::slice::Iter<'_, i32>, [closure@src/main.rs:4:45: 4:62]>` in the current scope
--> src/main.rs:4:64
|
4 | let drained: Vec<i32> = v.iter().filter(|e| (*e) % 2 == 0).drain(..).collect();
| ^^^^^
我查看了几个备选方案,none 其中似乎符合我的要求:
Vec::retain
从向量中删除元素,但不归还已删除元素的所有权。v.drain(..).filter(condition).collect()
returnsdrained
的正确值,但清空了整个向量。
不在稳定的 Rust 1.33.0 中。有一个名为 drain_filter
的不稳定的夜间功能完全符合您的要求:
#![feature(drain_filter)]
fn main() {
let mut v: Vec<i32> = vec![1, 2, 3, 4, 5, 6];
let drained: Vec<i32> = v.drain_filter(|&mut e| e % 2 == 0).collect();
assert_eq!(v, vec![1, 3, 5]);
assert_eq!(drained, vec![2, 4, 6]);
}
作为稳定的解决方法,您可以使用 Iterator::partition
,但它不会重复使用内存:
fn main() {
let v: Vec<i32> = vec![1, 2, 3, 4, 5, 6];
let (drained, v): (Vec<_>, Vec<_>) = v.into_iter().partition(|&e| e % 2 == 0);
assert_eq!(v, vec![1, 3, 5]);
assert_eq!(drained, vec![2, 4, 6]);
}
文档指出 Vec.retain 将操作 in-place,并按顺序访问每个元素,恰好一次。
fn drain_where<T, Pred : Fn(&T) -> bool>(source: &mut Vec<T>, pred: Pred) -> Vec<T>
where T : Copy {
let mut drained: Vec<T> = Vec::new();
source.retain(|item| {
if pred(item) { drained.push(*item); false } else { true }
});
drained
}