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

dy1byipe  于 2023-01-30  发布在  其他
关注(0)|答案(6)|浏览(129)

迭代器具有skip方法,该方法跳过前n元素:

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

我找不到一个方法来跳过迭代器中的第n个元素。我需要自己实现一些东西吗?还是有一个方法我还没有找到?

3npbholx

3npbholx1#

这似乎是一个非常具体的操作。在标准库或itertools板条箱中没有用于此操作的适配器。
尽管如此,它还是很容易实现的,可以枚举每个元素并过滤索引:

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

Playground

a2mppw5e

a2mppw5e2#

我偏爱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

jvidinwx

jvidinwx3#

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

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迭代器,从第一个创建。

u0sqgete

u0sqgete4#

如果你能接触到原始收藏,它可能是

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

jgzswidk5#

我不认为stdlib中有什么东西,但这里有另一个非常简单的方法来处理它。

fn main() {
    let (v, idx) = (vec!["foo", "bar", "baz", "qux"], 2_usize);

    let skipped = v[..idx].iter().chain(v[idx + 1..].iter());
    skipped.for_each(|&val| {
        dbg!(val);
    });
}

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=f47a28fd681fee2fe82b57c073d52648

pkwftd7m

pkwftd7m6#

更简洁:

let iter = vs
            .iter()
            .enumerate()
            .filter_map(|(i, el)| (i == n).then(|| el));

相关问题