How do I make a Range reverse on condition?

Issue

I have a range, that I want to reverse if a condition is satisfied. Since for i in 0..9 will iterate the same way as for i in 9..0 simply swapping out the numbers will not work. Also (0..9).stepy_by(-1) is not an option as .step_by() only accepts a usize. Therefore I tried so implement something like the following:

fn create_range(rev: bool) -> Range<usize> {
    if rev {
        0..9
    } else {
        (0..9).rev()
    }
}

Which unfortunately also des not work since 0..9 returns a Range<usize> but (0..9).rev() returns a Rev<Range<usize>> so the types do not match.

I ended up putting everything that I call within the loop in a function but I am not really satisfied with that.

if rev {
    for i in (0..9).rev() {
        do_stuff(i);
    }
} else {
    for i in 0..9 {
        do_stuff(i);
    }
}

The question is: Would it be simply possible to reverse a range if a condition is satisfied?

Solution

itertools has the type Either that can be used to return either of two compatible iterators:

use itertools; // 0.8.2

fn create_range(
    rev: bool,
) -> itertools::Either<impl Iterator<Item = usize>, impl Iterator<Item = usize>> {
    if !rev {
        itertools::Either::Left(0..9)
    } else {
        itertools::Either::Right((0..9).rev())
    }
}

fn main() {
    println!("Not reversed:");
    for a in create_range(false) {
        println!("{}", a);
    }

    println!("Reversed:");
    for a in create_range(true) {
        println!("{}", a);
    }
}

(Permalink to the playground)

Answered By – mcarton

Answer Checked By – Timothy Miller (AngularFixing Admin)

Leave a Reply

Your email address will not be published.