Rust 锈:如何过滤掉;无”;排放?

Rust 锈:如何过滤掉;无”;排放?,rust,iterator,Rust,Iterator,我的用例是,我希望扫描一个迭代器,并在原始迭代器的段上生成累积值(这是针对标记器的)。换句话说,它不是输入值和输出值之间的1对1映射。请注意,filter\u map()无法工作,因为我确实需要累加器值 我找到了.scan(),这几乎就是我想要的: #![允许(未使用)] fn main(){ 设a=[1,2,3]; 设mut iter=a.iter().scan(1,| state,&x |{ 如果x==2{ 不返回任何值; } //每一次迭代,我们都将状态乘以元素 *状态=*状态*x; //

我的用例是,我希望扫描一个迭代器,并在原始迭代器的段上生成累积值(这是针对标记器的)。换句话说,它不是输入值和输出值之间的1对1映射。请注意,
filter\u map()
无法工作,因为我确实需要累加器值

我找到了
.scan()
,这几乎就是我想要的:

#![允许(未使用)]
fn main(){
设a=[1,2,3];
设mut iter=a.iter().scan(1,| state,&x |{
如果x==2{
不返回任何值;
}
//每一次迭代,我们都将状态乘以元素
*状态=*状态*x;
//然后,我们将产生状态的否定
一些(-*州)
});
println!(“{:?},&iter.next());
println!(“{:?},&iter.next());
println!(“{:?},&iter.next());
}
除了上述输出

Some(-1)
None
Some(-3)
当我想要它输出时

Some(-1)
Some(-3)
None
而且,不管你怎么想,这是行不通的:

Some(-*状态)
}).filter(|x | x.is_some());
因为我实际上并没有迭代
选项
s:

error[E0599]: no method named `is_some` found for reference `&{integer}` in the current scope
  --> src/main.rs:15:21
   |
15 |     }).filter(|x| x.is_some());
   |                     ^^^^^^^ method not found in `&{integer}`
因此,就像迭代器方法被有意地屏蔽在“缺少收益率值”的情况下一样


你知道我怎样才能a)过滤掉那些缺失的收益率,或者b)以完全不同的方式完成上述任务吗?

你可以使用
过滤器映射
并在迭代器之外的变量中创建你自己的累加器:

fn main(){
设a=[1,2,3];
让mut state=1;
设mut iter=a.iter().filter_映射(|&x|){
如果x==2{
不返回任何值;
}
//每一次迭代,我们都将状态乘以元素
状态=状态*x;
//然后,我们将产生状态的否定
一些(州)
});
println!(“{:?},&iter.next());//一些(-1)
println!(“{:?},&iter.next());//一些(-3)
println!(“{:?},&iter.next());//无
}

仅打印3
iter.next()
应该是一个非常少见的用例。大多数情况下,会循环到
None
或在迭代器上使用类似
fuse
collect
的函数。每个函数都会在第一个
None
之后剪切所有结果。因此,从迭代器返回
None
意味着:终止迭代器

因此,您应该避免在扫描闭包中终止迭代器,例如

    let mut iter = a.iter().scan(1, |state, &x| {
        if x == 2 {
            return Some(None); // continue, but without value
        }
    
        // each iteration, we'll multiply the state by the element
        *state = *state * x;
    
        // then, we'll yield the negation of the state
        Some(Some(-*state)) // continue with value
    }).flatten(); // remove all missing values
或者通过将扫描与过滤器分离:

let mut iter = a
    .iter()
    .scan(1, |state, &x| {
      if x == 2 {
        return Some((x, *state));
      }

      // each iteration, we'll multiply the state by the element
      *state = *state * x;

      // then, we'll yield the negation of the state
      Some((x, -*state))
    })
    .filter_map(|(x, state)| if x == 2 { None } else { Some(state) });

在这种情况下,您可以在扫描之前放置一个过滤器
让mut iter=a.iter().filter(|&x | x!=2).扫描(1,| state,&x |{..})
,但我假设您的实际情况更复杂?是的,我可能举了一个不好的例子。我想做的是标记一些代码,例如从['l','e','t','f','o','o','''''''''''''''''''''=']到['let','foo','=']。因此,输入值最终将“分组”为数量较少的输出值。这可以通过.scan()来实现,如果我在没有完整标记时返回None,然后在生成的迭代器中没有这些清单的话。您可能想从itertools板条箱中查看一下,它似乎是为这种用例设计的。因为它从不从
scan()
返回
None
,代码没有利用
scan
的功能来终止迭代。它可以使用Coder-256所示的
filter\u map
,并避免
Some(Some(…)
。此解决方案旨在避免迭代器外部的状态(纯函数方法)。我添加了另一个变体来实现这一点。
Some(Some(…)
除了看起来很奇怪之外,还有什么不对?
选项本身没有什么不对,只是单个
选项更容易理解和推理。在这种情况下,根据优化器的智能程度,前者可能会稍微慢一点。避免外部状态也很好(虽然仍然不是纯粹的功能,因为闭包会改变状态),所以我想这是一个品味的问题
filter\u map
似乎更简单,使用频率更高,我更喜欢在任何时候都可以使用它,而不是
scan
。我的目标是在上述所有结果完成之前不终止它。.next()的显式使用只是为了举例说明。我可能说得不够清楚。是的,我最后做了几乎相同的事情,但使用了scan();我只是在选项中双重包装这些值,然后进行过滤。有点笨重,但避免外部状态。我对这种策略的任何一种变化都感觉不太好,但它完成了任务。