Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Iterator that returns each Nth value

Tags:

rust

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)?

like image 990
anula Avatar asked Apr 22 '16 15:04

anula


2 Answers

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);
like image 134
Nic Avatar answered Oct 02 '22 09:10

Nic


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.

like image 33
Shepmaster Avatar answered Oct 02 '22 10:10

Shepmaster