Search code examples
rustiteratorcycle

Cycle a Rust iterator a given number of times


How do I cycle through an iterator a finite number of times?

I would expect the output of something like this to be 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3 and then stop:

vec![1, 2, 3].iter().cycle(4)
//                         ^ but .cycle() doesn't take an argument...

I don't know the length of the iterator to begin with.


Solution

  • One simple way is to repeat the iterator itself, take the first 4 and flatten:

    fn main() {
        let v = vec![1, 2, 3];
        let res = std::iter::repeat(v.iter())
            .take(4)
            .flatten()
            .collect::<Vec<_>>();
        dbg!(res);
    }
    

    Some micro-benchmark result using code in this gist comparing 3 different approaches:

    • repeat-take-flatten in this answer
    • hand-rolled loop
    • a cycle_n implementation mimicking Iterator::cycle.

    Kudos to rustc, cycle_n consistently outperforms the other two when the input is reasonably large whereas repeat-take-flatten performs the best for small input.

    Micro-benchmark between repeat-take-flatten, hand-rolled loop and <code>cycle_n</code>