我想迭代 aVec
对其中的对象执行各种操作(这比usize
s 更复杂),并且如果命令停止迭代,则仅保留尚未处理的对象。
fn main() {
let _ = iterate();
}
fn iterate(){
let mut objs_for_processing = Vec::new();
for i in 0..10 {
objs_for_processing.push(i);
}
let mut n = 0;
objs_for_processing.retain(|obj| {
n += 1;
if n > 3 {
println!("STOP iteration!...");
return true // i.e. retain
}
println!("iteration, do some business with obj {}", obj);
false
});
println!("objs_for_processing.len() {} {:#?}", objs_for_processing.len(), objs_for_processing);
}
很明显,上述问题是您必须完成所有迭代,即使您知道要保留所有其他元素......
我发现了这个问题和这个问题。后者似乎更有希望。但事实证明,据我所知,您无法更改 闭retain
包的返回类型(即接受 a Result
,因此您可以返回 an Err
,这将停止迭代)。
我发现的唯一解决方案是克隆Vec
,使用普通迭代,然后在处理时for ... in
从克隆(称为 )中删除项目,使用相当麻烦的depleted_vec
let index = depleted_vec.iter().position(|x| x == obj).unwrap();
depleted_vec.remove(index);
...然后分配objs_for_processing
给depleted_vec
. 至少我可以用这种方式break
来停止迭代。
这似乎是一件相当合理的事情:难道没有一些更优雅的方法来做到这一点吗?
注意,我还想知道是否可能有一个Iterator
基于 - 的解决方案,所以我尝试使用iter().filter(...).collect()
... 这会产生Vec
a &usize
,而不是usize
。因此它也许可以使用,但需要额外的处理成本。不漂亮:只是感觉应该有更好的东西。
所以如果我理解正确的话,你需要做两件事:
这是有效完成此操作的循环:
extract_if
尽管实验性API 可以很好地满足您的用例(但仍会迭代所有内容),但我认为没有必要提出其他任何东西。但是,如果这确实是一个工作队列,那么您最好首先使用 VecDeque。
游乐场链接:https://play.rust-lang.org/? version=stable&mode=debug&edition=2021&gist=78468b26d34a29009b090a969fd9d5f3
您不需要克隆
Vec
,只需使用索引进行迭代并删除元素即可:这不会像
retain()
(因为它可以批量删除)那么有效,但它可能对你来说并不重要。