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

时间:2018-02-07 23:17:57

标签: 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();
}

但是我得到了这些编译错误:

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]>>`

奇怪的是,DoubleEndedIterator是为SkipWhile实施的。实际上,SkipWhile甚至实现了rev()See here

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

3 个答案:

答案 0 :(得分:5)

用于反转的迭代器适配器仅适用于可以从两端中的任何一端遍历的迭代器(例如,它是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);
}

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

let piece = &vec[..new_len];

Playground

答案 1 :(得分:4)

如错误消息所示:

  1. DoubleEndedIterator 未实现特征SkipWhile<...> - 请查看SkipWhile的实施情况:

    pub struct SkipWhile<I, P> {
        iter: I,
        flag: bool,
        predicate: P,
    }
    

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

  2. 期望结构Vec,找到结构Rev - 您仍然有一个迭代器,但是您试图将它存储在必须存储Vec的位置。你不能把类型A放在需要类型B的地方。
  3. 我会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]);
    }
    
      

    DoubleEndedIterator已针对SkipWhile实施。

    事实并非如此。如果您查看SkipWhile的文档,则不会列出它实现DoubleEndedIterator。以下是它实现的特征示例:FusedIterator

      

    事实上,SkipWhile甚至实现了rev()

    实际上并非如此。 Iterator::rev仅在SelfSkipWhile)实施DoubleEndedIterator的条件下实施,而不是fn rev(self) -> Rev<Self> where Self: DoubleEndedIterator,

    https://address.com/page/#client/side/route

答案 2 :(得分:2)

为了开始,这是一个非常狡猾的解决方案:

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 = vec.into_iter().rev().collect();
}