迭代器有一个 skip
方法,可以跳过前 n
个元素:
let list = vec![1, 2, 3];
let iterator = list.iter();
let skip_iter = iterator.skip(2); //skip the first 2 elements
我找不到一种方法来跳过迭代器中仅为第n
个元素。我是否需要自己实现一些东西,或者有一种我还没找到的方法?
这似乎是一个非常特定的操作。标准库或itertools
crate中都没有适配器适用于此。
不过这很容易实现。可以枚举每个元素并过滤索引:
iter.enumerate().filter(|&(i, _)| i != n).map(|(_, v)| v)
:游乐场。我偏爱使用 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);
}
:游乐场。.filter(..)
有什么优势吗?它看起来更长,但没有任何收益。 - Centrilfilter
зљ„и§Әе†іж–№жҰ€е°†иү”е›һеЊ…еђ«зөұеә•зљ„е…ѓз»„пәЊиЂЊиү™дёҒи§Әе†іж–№жҰ€е°†иү”е›һжІҰжњ‰зөұеә•зљ„еџғзҰЂе…ѓзө гЂ‚иү™еЏ–е†ідғҺж‚Ёжѓіи¦Ѓд»Ђд№€ж ·зљ„з»“жһњгЂ‚ - user25064filter_map
闭包在 Rust 1.50 中可以更加简洁,如果你喜欢的话:|(i, e)| (i != n).then(|| e)
。 - Orezlet items = ["a", "b", "c", "d"];
let skipped_2nd = items.iter().take(1).chain(items.iter().skip(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]);
}
Skip
迭代器。我认为标准库中没有这样的东西,但下面是另一种相当简单的解决方法。
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);
});
}
for_each()
才不会出错。 - StargateurIndex<RangeTo<usize>> + Index<RangeFrom<usize>>
,对吧?例如,如果我将 v
更改为 [&'static str; 4]
或 &[&'static str; 4]
而不是 Vec
,它似乎可以正常工作。编辑:错别字。 - n8henriefor_each
提出抱怨。那只是你的观点,还是在其他地方被正式诋毁了? - n8henrieVec
是 OP 在他们的示例中使用的内容,由于所讨论的用例需要一个序列(应该保持顺序以使跳过有意义),我不明白为什么你对我在我的答案中使用它有异议。https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.for_each 特别提到 chain
是 for_each
可能具有优势的情况之一,因此似乎可能有某些理由更喜欢它。对吗?编辑:错别字 - n8henrielet iter = vs
.iter()
.enumerate()
.filter_map(|(i, el)| (i == n).then(|| el));
enumerate().filter(|(i, v)| (i + 1) != n).map(|(i, v)| v)
来跳过第n
个元素。 - EvilTak