迭代器具有skip方法,该方法跳过前n元素:
skip
n
let list = vec![1, 2, 3]; let iterator = list.iter(); let skip_iter = iterator.skip(2); //skip the first 2 elements
我找不到一个方法来跳过迭代器中的第n个元素。我需要自己实现一些东西吗?还是有一个方法我还没有找到?
3npbholx1#
这似乎是一个非常具体的操作。在标准库或itertools板条箱中没有用于此操作的适配器。尽管如此,它还是很容易实现的,可以枚举每个元素并过滤索引:
itertools
iter.enumerate().filter(|&(i, _)| i != n).map(|(_, v)| v)
Playground
a2mppw5e2#
我偏爱filter_map版本
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); }
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迭代器,从第一个创建。
Skip
u0sqgete4#
如果你能接触到原始收藏,它可能是
let items = ["a", "b", "c", "d"]; let skipped_2nd = items.iter().take(1).chain(items.iter().skip(2));
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
pkwftd7m6#
更简洁:
let iter = vs .iter() .enumerate() .filter_map(|(i, el)| (i == n).then(|| el));
6条答案
按热度按时间3npbholx1#
这似乎是一个非常具体的操作。在标准库或
itertools
板条箱中没有用于此操作的适配器。尽管如此,它还是很容易实现的,可以枚举每个元素并过滤索引:
Playground
a2mppw5e2#
我偏爱
filter_map
版本Playground
jvidinwx3#
我已经想跳过一些范围了,我认为最好的方法是创建一个迭代器:
原理是使用2个不同的迭代器:第一个由用户给定,第二个是
Skip
迭代器,从第一个创建。u0sqgete4#
如果你能接触到原始收藏,它可能是
jgzswidk5#
我不认为stdlib中有什么东西,但这里有另一个非常简单的方法来处理它。
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=f47a28fd681fee2fe82b57c073d52648
pkwftd7m6#
更简洁: