Rust 可选地在自定义迭代器`next()`函数中调用`skip`

Rust 可选地在自定义迭代器`next()`函数中调用`skip`,rust,iterator,Rust,Iterator,我有一个自定义迭代器,我想在自定义.next()方法中选择调用.skip(…)。但是,由于Skip!=迭代器 示例代码如下所示: struct CrossingIter<'a, T> { index: usize, iter: std::slice::Iter<'a, T>, } impl<'a, T: Float> Iterator for CrossingIter<'a, T> { type Item = (usize

我有一个自定义迭代器,我想在自定义
.next()
方法中选择调用
.skip(…)
。但是,由于
Skip!=迭代器

示例代码如下所示:

struct CrossingIter<'a, T> {
    index: usize,
    iter: std::slice::Iter<'a, T>,
}

impl<'a, T: Float> Iterator for CrossingIter<'a, T> {
    type Item = (usize, T);


    fn next(&mut self) -> Option<(usize, T)> {
        let iter = (&mut self.iter).enumerate();
         
        let iter = if self.index == 0 {
            self.index += 3;
            iter.skip(3)
        } else {
            iter
        }

        // lots of code here working with the new iterator        

        iter.next()
    }
}
struct CrossingIter,
}
恳求{
类型项=(usize,T);
fn下一步(&mut self)->选项{
让iter=(&mut self.iter).enumerate();
设iter=if self.index==0{
自指数+=3;
iter.skip(3)
}否则{
iter
}
//这里有很多使用新迭代器的代码
iter.next()
}
}
问题是调用
.skip(3)
后,
iter
的类型发生了变化。一种解决方案是在
if
语句的每个分支中复制
//大量代码…
,但我不希望这样


我的问题是:有没有一种方法可以有条件地对迭代器应用
skip(…)
,并继续使用它而不复制一堆代码?

我认为@Silvio的答案是一个更好的观点


您可以在
else
分支中调用
skip(0)
而不是
iter
本身

enumerate
生成的迭代器的返回值与您的定义不匹配:
fn next(&mut self)->Option
。你需要绘制地图

以下是一个工作示例:

use num::Float;

struct CrossingIter<'a, T> {
    index: usize,
    iter: std::slice::Iter<'a, T>,
}

impl<'a, T: Float> Iterator for CrossingIter<'a, T> {
    type Item = (usize, T);


    fn next(&mut self) -> Option<(usize, T)> {
        let iter = (&mut self.iter).enumerate();
         
        let mut iter = if self.index == 0 {
            self.index += 3;
            iter.skip(3)
        } else {
            iter.skip(0)
        };

        // lots of code here working with the new iterator        

        iter.next().map(|(i, &v)| (i, v))
    }
}
使用num::Float;
struct CrossingIter,
}
恳求{
类型项=(usize,T);
fn下一步(&mut self)->选项{
让iter=(&mut self.iter).enumerate();
设mut iter=if self.index==0{
自指数+=3;
iter.skip(3)
}否则{
iter.skip(0)
};
//这里有很多使用新迭代器的代码
iter.next().map(|(i和v)|(i,v))
}
}
旨在构造一个新的迭代器,它在希望代码保持(至少在表面上)不可变的情况下非常有用。但是,在您的情况下,您希望在保持现有迭代器有效的同时,使其前进

有一个可以做你想做的,但它是夜间的,所以它不会在稳定的铁锈上运行

if self.index == 0 {
  self.index += 3;
  self.iter.advance_by(3);
}
我们可以滥用权力来得到我们想要的,但这不是很习惯用语

if self.index == 0 {
  self.index += 3;
  self.iter.nth(2);
}
如果我在生产中看到这些代码,我会非常困惑

最简单且不太令人满意的答案是将
advance\u作为辅助函数重新实现。是可用的,并且很容易适应

fn my_advance_by(iter: &mut impl Iterator, n: usize) -> Result<(), usize> {
  for i in 0..n {
    iter.next().ok_or(i)?;
  }
  Ok(())
}

我实际上使用了
skip_while(F)
,如果我有两个不同的
F
,我又会得到不同的类型……让事情稍微复杂一点,我实际上使用了
skip_while(F)
,这取决于一事实,即如果谓词为false,则不会消耗任何内容。我想我可以先把事情看清楚?你的解决方案是否可能是一个简单的for循环,带有
next()
break
?有时,最简单的解决方案可能是最好的,在较低级别的语言中,这一点会加倍,例如RustI尝试了
循环
,但由于某些原因,它比使用
跳过时慢。也许我应该再试一次,不过……我完全放弃了迭代器,直接在切片上执行了
for
循环,自己跟踪索引。这似乎很好地发挥了作用:-)
struct CrossingIter<'a, T> {
  index: usize,
  iter: std::iter::Skip<std::slice::Iter<'a, T>>,
}