I have a Vec<T>
that has elements matching a pattern. I want to remove all trailing instances of the elements that match the pattern.
For example, I have a Vec<i32>
and the pattern is (|x| x == 0)
. If the input was: vec![0, 1, 0, 2, 3, 0, 0]
, the output should be: vec![0, 1, 0, 2, 3]
To do this I tried:
fn main() {
let mut vec = vec![0, 1, 0, 2, 3, 0, 0];
vec = vec.into_iter().rev().skip_while(|&x| x == 0).rev();
}
But I get these compiler errors:
error[E0277]: the trait bound `std::iter::SkipWhile<std::iter::Rev<std::vec::IntoIter<{integer}>>, [closure@src/main.rs:3:44: 3:55]>: std::iter::DoubleEndedIterator` is not satisfied
--> src/main.rs:3:57
|
3 | vec = vec.into_iter().rev().skip_while(|&x| x == 0).rev();
| ^^^ the trait `std::iter::DoubleEndedIterator` is not implemented for `std::iter::SkipWhile<std::iter::Rev<std::vec::IntoIter<{integer}>>, [closure@src/main.rs:3:44: 3:55]>`
error[E0308]: mismatched types
--> src/main.rs:3:11
|
3 | vec = vec.into_iter().rev().skip_while(|&x| x == 0).rev();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `std::vec::Vec`, found struct `std::iter::Rev`
|
= note: expected type `std::vec::Vec<{integer}>`
found type `std::iter::Rev<std::iter::SkipWhile<std::iter::Rev<std::vec::IntoIter<{integer}>>, [closure@src/main.rs:3:44: 3:55]>>`
The strange thing is that DoubleEndedIterator
is implemented for SkipWhile
. In fact, SkipWhile
even implements rev()
. See here.
What am I doing wrong? Is there a better approach?
The iterator adaptor for reversal only works for iterators which can be traversed from any of the two ends (as in, it is a DoubleEndedIterator
). While this is the case for the original one, this is no longer possible from the moment we include skip_while
. In order to follow that approach, you would have to collect the rest of the reversed vector, and only then reverse again.
I, on the other hand, would just choose to fetch the index of the first trailing zero and truncate the vector with it.
let mut vec = vec![0, 1, 0, 2, 3, 0, 0];
if let Some(i) = vec.iter().rposition(|x| *x != 0) {
let new_len = i + 1;
vec.truncate(new_len);
}
... or just grab a slice instead:
let piece = &vec[..new_len];
Playground
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