Comparing every element in a vector with the next one

This can be done in several ways.

Using slice::windows

slice::windows:

Returns an iterator over all contiguous windows of length size.

In this case, the window size will be 2 so windows will return an iterator which will mask 2 elements and it will move to the right on every iteration.

initial position : [|0, 5|, 10, 40, 30] // &[0, 5]
next position    : [0, |5, 10|, 40, 30] // &[5, 10]

Here is an applied solution to your problem:

fn main() {
    let data: Vec<Obj> = vec![Obj { i: 0 }, Obj { i: 1 }, Obj { i: 2 }, Obj { i: 3 }];

    let is_valid = data.windows(2).all(|w| w[0].is_valid_next(&w[1]));

    println!("Is consecutive -> {:?}", is_valid); // true
}

Playground

Please note that direct index access of a slice might cause a panic, but since the produced slice from Windows iterator will be the same size as the argument to windows, it will be fine to access elements directly by index as long as the index is less than the window size.

Using Iterator::zip

You can compare the current element with the next one by using two different iterators of same Vec with std::iter::Zip.

The iterator elements from the first iterator (data.iter()) will represent the current element. Elements from the second iterator (data.iter().skip(1)) will represent the next element.

Here is the implementation:

fn main() {
    let data: Vec<Obj> = vec![Obj { i: 0 }, Obj { i: 1 }, Obj { i: 2 }];

    let is_valid = data
        .iter()
        .zip(data.iter().skip(1))
        .all(|(current, next)| current.is_valid_next(next));

    println!("Is consecutive -> {:?}", is_valid); // true
}

Playground

If you are sure your Vec is not empty, you can use slices to create the iterators: &data[1..] instead of data.iter().skip(1) (sample). This will panic if you have an empty Vec.

Leave a Comment