What is the normative method for iterating through a Vec in an arbitrary direction?

The code sums up my question succinctly. Do I need to do some type gymnastics or a basic loop{} construct to make this work, or is there a way to have step_by() decrement a usize type?

// What is the normative method for iterating through
// a Vec in an arbitrary direction?
fn main() {
    const SIZE: usize = 4;
    let v: Vec<u32> = vec![0; SIZE];
    // The compiler complains about .step_by(-1):
    // error[E0600]: cannot apply unary operator `-` to type `usize`
    for i in ((SIZE-1)..=0).step_by(-1) {
        v[i] = 1 + (i as u32);
    }
    println!("{:?}", v);
}

I guess one idiomatic way would be to use iterator adapters:

fn main() {
    const SIZE: usize = 4;
    let mut v: Vec<u32> = vec![0; SIZE];
    for (i, elem) in v.iter_mut().rev().enumerate() {
        *elem = 1 + (i as u32);
    }
    println!("{:?}", v);
}

prints:

[4, 3, 2, 1]
1 Like

In my interpretation of OPʼs code, .enumerate().rev() might be closer to what they tried than .rev().enumerate().


@unknown_babel, note that indeed, as @rikyborg mentioned, it's more idiomatic to use iterator over the Vec itself than to use indices. If you ever need to iterate over a range of integers backwards anyways, note that for i in (0..SIZE).rev() works, too.

1 Like

Thanks for the help. I am now using code that resembles what is posted below. I am not using enumerate() because I need access to arbitrary elements of the vector while inside the loop, and not necessarily the element indexed by i.

fn main() {
    const SIZE: usize = 8;
    let mut v: Vec<u32> = vec![0; SIZE];
    for i in (0..SIZE).rev().step_by(2) {
        v[i] = 5 * (1 + (i as u32));
        v[i - 1] = v[i] % 3
    }
    println!("{:?}", v);
}

Output:

[1, 10, 2, 20, 0, 30, 1, 40]

For that particular case you could use

    for (i, pair) in (1..).zip(v.chunks_exact_mut(2)) {
        pair[0] = i % 3;
        pair[1] = i * 10;
    }
3 Likes