I want to compare every element of a vector with the next one. I found the following solution but it is not so readable.
struct Obj {
i: u32,
}
impl Obj {
fn is_valid_next(&self, next: &Obj) -> bool {
self.i + 1 == next.i
}
}
fn main() {
let data: Vec<Obj> = vec![Obj { i: 0 }, Obj { i: 2 }, Obj { i: 2 }];
let mut previous: Option<Obj> = None;
let mut is_valid = true;
for current in data.into_iter() {
match previous {
Some(p) => {
is_valid = p.is_valid_next(¤t);
if !is_valid {
break;
}
}
None => {}
}
previous = Some(current);
}
println!("is valid {}", is_valid);
}
This can be done in several ways.
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.
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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With