try_fold 是停止无限迭代的首选方法还是有更多惯用的替代方法?

jgp*_*iva 2 iteration rust

我正在寻找中断无限迭代器迭代的方法。我发现这try_fold达到了我的目标。然而,这需要Err在成功的案例上做返回一个尴尬的事情。我想了解的是,这是否是一种惯用的做事方式。我能想到的唯一另一种方法是使用常规的for,或者像findwhile 保持外部状态的东西(感觉更奇怪!)。我知道在 clojure 中有reduced,但我找不到 rust 的等价物。

这是一个最小可行的例子。该示例围绕初始 Vec 循环,对每个项目进行求和,并在第一个大于 10 的总和处停止。即它返回 12,因为1 + 5 - 3 + 1 + 5 - 3 + 1 + 5 = 12

fn main() {
    let seed = vec![1, 5, -3];

    let res = seed.iter().cycle().try_fold(0, |accum, value| {
        let next = accum + value;
        if next > 10 {
            Err(next)
        } else {
            Ok(next)
        }
    });
    if let Err(res) = res {
        println!("{:?}", res);
    } else {
        unreachable!();
    }
}
Run Code Online (Sandbox Code Playgroud)

游乐场链接

对我来说感觉很奇怪的部分是if let Err(res) = res成为积极条件并且真的是退出循环的唯一途径(因此为什么另一个分支无法访问)。

有没有更好的办法?

Pet*_*all 6

您可以使用scanfind

fn main() {
    let seed = vec![1, 5, -3];
    let res = seed
        .iter()
        .cycle()
        .scan(0, |accum, value| {
            *accum += value;
            Some(*accum)
        })
        .find(|&x| x > 10)
        .unwrap();
    println!("{:?}", res);
}
Run Code Online (Sandbox Code Playgroud)

这实际上比使用fold_whilefrom稍微短一些itertools,如下所示:

use itertools::{FoldWhile::{Continue, Done}, Itertools};

fn main() {
    let seed = vec![1, 5, -3];
    let res = seed
        .iter()
        .cycle()
        .fold_while(0, |accum, value| {
            let next = accum + value;
            if next > 10 {
                Done(next)
            } else {
                Continue(next)
            }
        })
        .into_inner();
    println!("{:?}", res);
}
Run Code Online (Sandbox Code Playgroud)


Kri*_*ish 5

简单,正常迭代即可

fn main() {
    let seed = vec![1, 5, -3];
    let mut accum = 0;
    for value in seed.iter().cycle() {
        accum += value;
        if accum > 10 {
            break;
        }
    }
    println!("{:?}", accum)
}
Run Code Online (Sandbox Code Playgroud)


小智 2

如果您不介意使用完善的外部库,请考虑使用itertools::fold_while 。如果您喜欢这种编程风格,可能还有其他有用的扩展。

  • @jgpaiva 在 Rust 中,使用外部板条箱是常态,我什至可以说,如果流行的板条箱能让你的代码更干净,那么使用流行的板条箱是惯用的。 (2认同)