Rust 锈菌是否有一种特性,允许群体进行折叠,而不需要像协同进化这样的实验特征?

Rust 锈菌是否有一种特性,允许群体进行折叠,而不需要像协同进化这样的实验特征?,rust,iterator,delimiter,yield,Rust,Iterator,Delimiter,Yield,我想避免实验性的功能,所以我正在考虑发电机之前的其他选择 我有一个向量v,它由0分隔成多个组。这些分隔组的总和可以通过for循环或迭代器累加: fn main() { let v = vec![55, 23, 75, 0, 12, 34, 0, 97, 71, 23, 0]; // for loop let mut acc = 0; for &vi in &v { acc += vi; if vi == 0 {

我想避免实验性的功能,所以我正在考虑发电机之前的其他选择

我有一个向量
v
,它由0分隔成多个组。这些分隔组的总和可以通过for循环或迭代器累加:

fn main() {
    let v = vec![55, 23, 75, 0, 12, 34, 0, 97, 71, 23, 0];

    // for loop
    let mut acc = 0;

    for &vi in &v {
        acc += vi;

        if vi == 0 {
            println!("for yield {}", acc);
            acc = 0;
        }
    }

    // iter 'loop'
    v.iter()
        .scan(0, |acc, &vi| {
            *acc += vi;
            Some(if vi == 0 {
                let total = *acc;
                *acc = 0;
                Some(total)
            } else {
                None
            })
        })
        .filter_map(|acc| acc)
        .for_each(|acc| println!("iter yield {:?}", acc));
}
scan
被用作一个特殊的协同程序,当迭代器生成值时返回
Some(value)
,当迭代器仍在处理时返回
None
<代码>无将被过滤掉,并打印总和

上面的例子有些琐碎,因为两个操作产生相同的结果;但是,我的项目需要消化数据流(无法收集到矢量中)并有条件地折叠它们(例如,如果
acc
可被10整除,而不是0分隔,则这里的条件可能是)


折叠条件本身是管道化的,这样每个管道都可以提供一个迭代器(想想嵌套的协程)。我想看看他们是否使用迭代器,是否有一种替代方法来代替
Iterator::scan
->
Iterator::filter\u map
。请记住,收集整个数据流是不可能的,因为数据流可能是无限的。

for循环的
或带有
scan()的版本没有问题。
。如果我在寻找更清晰的选择,我会考虑使用。此版本非常优雅,几乎满足您的需求:

use itertools::Itertools;

v.iter()
    .group_by(|&&vi| vi != 0)
    .into_iter()
    .map(|(_, group)| group.sum::<u32>())
    .for_each(|s| println!("sum {}", s));

不完美,但仍然比原始公式稍微优雅一些,因为它使分组更加明确。

用零将分组应该像
v.split(|vi | vi==0)
一样简单,然后可以使用
.map(|g | g.sum())
或类似的方法。不过,对于基于求和本身的拆分,我没有更好的解决方案。@kmdreko有没有办法用迭代器来实现这一点?我正在压缩一个大的对象流,压缩本身被管道化为4个阶段,因此收集到一个向量中会导致不希望的延迟。我看到Split特性专门用于字符串类型。我想知道我是否可以避免手动实现向量。关于如何使用向量的额外信息是使问题非主观的关键。目前,您只是有两种不同的方法来做同一件事,这两种方法都有效,并且有一个模糊的要求使它“更地道”。如果问题中的代码不满足您的需要,那么在问题中包含为什么不满足您的需要,并解释什么样的答案是可以接受的,这一点很重要。@trentcl我将在问题中添加额外的信息。谢谢你的建议。我对你在
scan
中使用术语“协同程序”感到困惑。在这里,
scan
如何像协同程序一样使用?协同例程应该能够暂停执行或将其切换到其他人,而您的代码两者都不能,它是一个普通的子例程。标题也提到了协同程序,但没有解释它们之间的联系。我的问题措辞不正确。请接受我的投票,但我将结束这个问题,并重新发布更正后的版本。
v.iter()
    .group_by(|&&vi| vi != 0)
    .into_iter()
    .filter_map(|(filt, group)| if filt { Some(group.sum::<u32>()) } else { None })
    .for_each(|s| println!("sum {}", s));