Iterators have a skip
method that skips the first n
elements:
let list = vec![1, 2, 3];
let iterator = list.iter();
let skip_iter = iterator.skip(2); //skip the first 2 elements
I could not find a method to skip only the n
-th element in the iterator. Do I need to implement something on my own or is there a method somewhere I haven't found?
That seems to be a very specific operation. There is no adaptor for that in the standard library or the itertools
crate.
It's easy to implement nonetheless. One could enumerate each element and filter on the index:
iter.enumerate().filter(|&(i, _)| i != n).map(|(_, v)| v)
I am partial to the filter_map
version
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);
}
I already wanted to skip some range. The best in my opinion is to create an iterator:
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]);
}
The principle is to use 2 different iterators: the first one is given by the user, the second one is a Skip
iterator, created from the first one.
If you have access to original collection, it could be
let items = ["a", "b", "c", "d"];
let skipped_2nd = items.iter().take(1).chain(items.iter().skip(2));
I don't think there is something in the stdlib, but here's yet another pretty simple way to go about it.
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);
});
}
More concise:
let iter = vs
.iter()
.enumerate()
.filter_map(|(i, el)| (i == n).then(|| el));
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.