I have an iterator iter
; is it possible to convert it into an iterator that iterates over each Nth element? Something like iter.skip_each(n - 1)
?
6
votes
2 Answers
8
votes
As of Rust 1.26, there is the Iterator::step_by
method in the standard library:
Basic usage:
let a = [0, 1, 2, 3, 4, 5]; let mut iter = a.iter().step_by(2); assert_eq!(iter.next(), Some(&0)); assert_eq!(iter.next(), Some(&2)); assert_eq!(iter.next(), Some(&4)); assert_eq!(iter.next(), None);
7
votes
As Dogbert said, use itertools' step
.
You are going to be in a world of hurt if you can't use external crates. The Rust ecosystem strongly encourages everything to be pushed to crates. Maybe you should just clone the repository locally and use it that way if you can.
Otherwise, write it yourself:
use std::iter::Fuse;
struct Nth<I> {
n: usize,
iter: Fuse<I>,
}
impl<I> Iterator for Nth<I>
where I: Iterator
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
let mut nth = None;
for _ in 0..self.n {
nth = self.iter.next();
}
nth
}
}
trait EveryNth: Iterator + Sized {
fn every_nth(self, n: usize) -> Nth<Self> {
Nth { n: n, iter: self.fuse() }
}
}
impl<I> EveryNth for I where I: Iterator {}
fn main() {
let x = [1,2,3,4,5,6,7,8,9];
for v in x.iter().every_nth(1) { println!("{}", v) }
println!("---");
for v in x.iter().every_nth(2) { println!("{}", v) }
println!("---");
for v in x.iter().every_nth(3) { println!("{}", v) }
println!("---");
for v in x.iter().every_nth(4) { println!("{}", v) }
println!("---");
for v in x.iter().every_nth(5) { println!("{}", v) }
println!("---");
for v in x.iter().every_nth(6) { println!("{}", v) }
}
Note this is different behavior from itertools. You didn't specify where in the cycle of N the iterator picks from, so I chose the one that was easiest to code.
step
iterator initertools
: bluss.github.io/rust-itertools/doc/itertools/… – Dogbertcargo build --target ...
, and (if you're usingstd
/core
) doubly so with the newrustup
that makes installing the standard library for new targets quite easy. It definitely gets much more annoying with crates with C dependencies, but pure Rust things likeitertools
should slot in seemlessly. – huon