如何跳过Rust迭代器中的第N个元素?

时间:2018-03-14 10:36:07

标签: iterator rust skip

迭代器使用skip方法跳过第一个n元素:

let list = vec![1, 2, 3];
let iterator = list.iter();
let skip_iter = iterator.skip(2); //skip the first 2 elements

我找不到只跳过迭代器中n - 元素的方法。我是否需要自己实施某些方法,或者我找不到某个方法?

4 个答案:

答案 0 :(得分:8)

这似乎是一个非常具体的操作。标准库或itertools包中没有适配器。

尽管如此,它仍然很容易实现。可以枚举每个元素并过滤索引:

iter.enumerate().filter(|&(i, _)| i != n).map(|(_, v)| v)

Playground

答案 1 :(得分:8)

我偏向filter_map版本

fn main() {
    let v = vec![1, 2, 3];
    let n = 1;
    let x: Vec<_> = v.into_iter()
        .enumerate()
        .filter_map(|(i, e)| if i != n { Some(e) } else { None })
        .collect();
    println!("{:?}", x);
}

Playground

答案 2 :(得分:2)

我已经想跳过一些范围了。我认为最好的是创建一个迭代器:

mod skip_range {
    use std::ops::Range;
    use std::iter::Skip;

    /// Either the user provided iterator, or a `Skip` one.
    enum Either<I: Iterator> {
        Iter(I),
        Skip(Skip<I>),
    }

    pub struct SkipRange<I: Iterator> {
        it: Option<Either<I>>,
        count: usize,
        range: Range<usize>,
    }

    impl<I: Iterator> SkipRange<I> {
        pub fn new(it: I, range: Range<usize>) -> Self {
            SkipRange { it: Some(Either::Iter(it)), count: 0, range }
        }
    }

    impl<I: Iterator> Iterator for SkipRange<I> {
        type Item = I::Item;

        fn next(&mut self) -> Option<Self::Item> {
            // If we are in the part we must skip, change the iterator to `Skip`
            if self.count == self.range.start {
                self.count = self.range.end;
                if let Some(Either::Iter(it)) = self.it.take() {
                    self.it = Some(Either::Skip(it.skip(self.range.end - self.range.start)));
                }
            } else {
                self.count += 1;
            }
            match &mut self.it {
                Some(Either::Iter(it)) => it.next(),
                Some(Either::Skip(it)) => it.next(),
                _ => unreachable!(),
            }
        }
    }
}

use skip_range::SkipRange;

fn main() {
    let v = vec![0, 1, 2, 3, 4, 5];
    let it = SkipRange::new(v.into_iter(), 2..4);

    let res: Vec<_> = it.collect();
    assert_eq!(res, vec![0, 1, 4, 5]);
}

原则是使用2个不同的迭代器:第一个是由用户给出的,第二个是Skip迭代器,是从第一个迭代器创建的。

答案 3 :(得分:0)

如果您有权访问原始收藏集,则可能是

let items = ["a", "b", "c", "d"];
let skipped_2nd = items.iter().take(1).chain(items.iter().skip(2));