vector.into_iter()。filter(some_non_trivial_function).collect()是否可接受

eri*_*ire 1 rust

因此,如果我有一个,mut v: Vec<Foo>并且我只想保留那些活着的

我会做

v = v.into_iter().filter(|&foo| non_trivial_function_returning_a_result(foo).is_ok()).collect()
Run Code Online (Sandbox Code Playgroud)

是否会分配一个新的媒介,然后将原来的向量销毁?有什么更好的方法可以做到这一点?

Waz*_*ner 5

Vec将使用您提供的代码分配新的代码。有几种可能的方法可以在没有分配的情况下执行此操作,这取决于您的约束(时间和稳定性)

Vec.retain
几乎最简单的方法就是使用Vec.retain

仅保留谓词指定的元素。

您可以像这样使用它:

let mut vec = vec![1, 2, 3, 4];
vec.retain(|&x| non_trivial_function_returning_a_result(x).is_ok());
assert_eq!(vec, [2, 4]);
Run Code Online (Sandbox Code Playgroud)

Vec.drain_filter
如果要对需要所有权的已删除元素执行某些操作,则可以使用该Vec.drain_filter方法。在撰写本文时,此方法仅在夜间生锈时可用。

您可以像这样使用它:

#![feature(drain_filter)]

let mut numbers = vec![1, 2, 3, 4, 5, 6, 8, 9, 11, 13, 14, 15];
for x in numbers.drain_filter(|x| non_trivial_function_returning_a_result(x).is_ok()) {
  // Do something with x
}
Run Code Online (Sandbox Code Playgroud)

如果您需要所有权,但不想使用夜间锈蚀,则可以手动进行。

let mut i = 0;
while i != vec.len() {
    if non_trivial_function_returning_a_result(&vec[i]).is_ok() {
        let val = vec.remove(i);
        // do something with val
    } else {
        i += 1;
    }
}
Run Code Online (Sandbox Code Playgroud)