跳出Vec::retain()?

问题描述 投票:0回答:1

我想迭代一个

Vec
对其中的对象执行各种操作(这比
usize
更复杂),并且,如果收到停止迭代的命令,则仅保留那些没有的对象尚未处理。

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 闭包的返回类型(即接受

Result
,因此您可以返回
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
来停止迭代。
这似乎是一件相当合理的事情:难道没有一些更优雅的方法来做到这一点吗?

NB 我还想知道是否可能存在基于

Iterator

的解决方案,因此我尝试使用

iter().filter(...).collect()
...这会产生
Vec
&usize
,而不是
usize
。因此它也许可以使用,但需要额外的处理成本。不漂亮:只是感觉应该有更好的东西。
    

rust iterator
1个回答
0
投票
Vec

,您只需使用索引进行迭代并删除元素即可:

let mut i = 0;
let mut n = 0;
while i < objs_for_processing.len() {
    if n > 3 {
        println!("STOP iteration!...");
        break;
    }
    
    if true {
        let obj = &objs_for_processing[i];
        println!("iteration, do some business with obj {}", obj);
        
        objs_for_processing.remove(i);
        // Don't increment `i`!
    } else {
        i += 1;
    }
    
    n += 1;
}

这不会像
retain()

那么有效(因为它可以批量删除),但这对你来说可能并不重要。

    

© www.soinside.com 2019 - 2024. All rights reserved.