仅删除与条件匹配的Vec的尾随元素

HiD*_*der 2 iterator rust

我有一个Vec<T>与模式匹配的元素.我想删除与模式匹配的元素的所有尾随实例.

例如,我有一个Vec<i32>和模式是(|x| x == 0).如果输入为:vec![0, 1, 0, 2, 3, 0, 0],则输出应为:vec![0, 1, 0, 2, 3]

为此,我试过:

fn main() {
    let mut vec = vec![0, 1, 0, 2, 3, 0, 0];
    vec = vec.into_iter().rev().skip_while(|&x| x == 0).rev();
}
Run Code Online (Sandbox Code Playgroud)

但我得到这些编译器错误:

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]>>`
Run Code Online (Sandbox Code Playgroud)

奇怪的是,这DoubleEndedIterator是为了实现SkipWhile.实际上,SkipWhile甚至是工具rev().看到这里.

我究竟做错了什么?有更好的方法吗?

E_n*_*ate 5

用于反转的迭代器适配器仅适用于可以从两端中的任何一端遍历的迭代器(如,它是a DoubleEndedIterator).虽然这是原始的情况,但从我们包括的那一刻起,这已不再可能skip_while.为了遵循这种方法,你必须收集反向矢量的其余部分,然后再反转.

另一方面,我只会选择获取第一个尾随零的索引并用它截断向量.

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);
}
Run Code Online (Sandbox Code Playgroud)

......或者只是抓住一片:

let piece = &vec[..new_len];
Run Code Online (Sandbox Code Playgroud)

操场


She*_*ter 5

正如错误消息所述:

  1. 该 traitDoubleEndedIterator未实现SkipWhile<...>- 看一下 的实现SkipWhile

    pub struct SkipWhile<I, P> {
        iter: I,
        flag: bool,
        predicate: P,
    }
    
    Run Code Online (Sandbox Code Playgroud)

    您无法反转构建的迭代器,SkipWhile因为当您添加从正面和背面拉出的能力时,它无法跟踪“当前”项目是否被跳过。

  2. 预期的结构体Vec,找到的结构体Rev——你仍然有一个迭代器,但你试图将它存储在Vec必须存储的地方。您不能将类型 A 放在需要类型 B 的地方。

我会collect向量,然后reverse它就位:

fn main() {
    let mut vec = vec![0, 1, 0, 2, 3, 0, 0];

    vec = vec.into_iter().rev().skip_while(|&x| x == 0).collect();
    vec.reverse();

    println!("{:?}", vec);
    assert_eq!(vec, [0, 1, 0, 2, 3]);
}
Run Code Online (Sandbox Code Playgroud)

DoubleEndedIterator是为SkipWhile.

这不是真的。如果您查看 的文档SkipWhile,它没有列出它实现的内容DoubleEndedIterator。下面是它确实实现性状的例子:FusedIterator

事实上,SkipWhile即使实现rev()

它实际上没有。Iterator::rev仅在Self(即SkipWhile)实现的条件下实现DoubleEndedIterator,而这不实现:

fn rev(self) -> Rev<Self>
where
    Self: DoubleEndedIterator, 
Run Code Online (Sandbox Code Playgroud)