How to create a lazy iterator of nested values (a nested loop iterator)?

I'm having trouble creating a lazy iterator that returns a tuple in the same way that a simple nested loop would:

for x in (0..5) {
    for y in (0..5) {
        for z in (0..5) {
            (x, y, z);
        }
    }
}

It seems quite simple but I've yet to find an iterator that can repeat each item n times, or multizip items out of lock-step. I've given it a few attempts but they all end up with me creating collections of duplicated indices such as below:

let x_iterator = (0..x_len)
    .into_iter()
    .flat_map(|x| iter::repeat(x).take(y_len).collect());
// ...

Or some such other combination of nested adapters that force me to eagerly evaluate the inner contents to get the resulting lazy iterator.

  1. Is there a simpler solution to creating a lazy iterator of these nested values?
  2. Is there a solution that can create tuples for n nested iterators (a, b, .., n) ?
(0..5)
    .flat_map(|a| (0..5).map(move |b| (a, b)))
    .flat_map(|(a, b)| (0..5).map(move |c| (a, b, c)))

The move handles the repeating by copying the integers, so if you want to do this with non-copy items, you'll need to clone them before the closure.

1 Like

Isn't that the Cartesian product you are looking for? Does itertools::iproduct do what you want?

3 Likes

This is exactly what I was looking for. I knew I couldn't have been looking for something not available somewhere.

1 Like