This can be done in several ways.
Using 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
}
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
}
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
.