一次迭代多个变量,重叠(
slice::windows
)或不重叠(
slice::chunks
)可能很有用.
这仅适用于切片;是否可以为迭代器执行此操作,为方便起见使用元组?
可以写下以下内容:
for (prev,next) in some_iter.windows(2) { ... }
如果没有,它可以作为现有迭代器的特征实现吗?
TL; DR:在任意迭代器/集合上拥有块和窗口的最佳方法是首先将它收集到Vec中并迭代它.
在Rust中,所要求的确切语法是不可能的.
问题是在Rust中,函数的签名取决于类型,而不是值,并且存在Dependent Typing时,实现它的语言很少(很难).
这就是为什么块和窗口返回子切片的原因; & [T]中的元素数量不是类型的一部分,因此可以在运行时决定.
让我们假装你要求:for some_iter.windows(2)中的切片然后.
支持这片的存储在哪里?
它无法生存:
>在原始集合中,因为LinkedList没有连续的存储
>在迭代器中,由于Iterator :: Item的定义,没有可用的生命周期
因此,不幸的是,切片只能在后备存储是切片时使用.
如果接受动态分配,则可以使用Vec< Iterator :: Item>作为分块迭代器的项目.
struct Chunks<I: Iterator> { elements: Vec<<I as Iterator>::Item>,underlying: I,} impl<I: Iterator> Chunks<I> { fn new(iterator: I,size: usize) -> Chunks<I> { assert!(size > 0); let mut result = Chunks { underlying: iterator,elements: Vec::with_capacity(size) }; result.refill(size); result } fn refill(&mut self,size: usize) { assert!(self.elements.is_empty()); for _ in 0..size { match self.underlying.next() { Some(item) => self.elements.push(item),None => break,} } } } impl<I: Iterator> Iterator for Chunks<I> { type Item = Vec<<I as Iterator>::Item>; fn next(&mut self) -> Option<Self::Item> { if self.elements.is_empty() { return None; } let new_elements = Vec::with_capacity(self.elements.len()); let result = std::mem::replace(&mut self.elements,new_elements); self.refill(result.len()); Some(result) } } fn main() { let v = vec!(1,2,3,4,5); for slice in Chunks::new(v.iter(),2) { println!("{:?}",slice); } }
将返回:
06001
精明的读者会意识到我偷偷地从窗户切换到了大块.
窗口更难,因为它多次返回相同的元素,这要求元素是克隆.此外,由于每次都需要返回完整的Vec,因此需要在内部保持Vec< Vec< Iterator :: Item>>.
这留给读者练习.
最后,关于性能的说明:所有这些分配都会受到伤害(特别是在Windows案例中).
最好的分配策略通常是分配一块内存然后实现(除非数量非常大,在这种情况下需要流式传输).
它在Rust中称为collect ::< Vec< _>>().
并且由于Vec具有块和窗口方法(通过实现Deref< Target = [T]>),因此您可以使用它:
for slice in v.iter().collect::<Vec<_>>().chunks(2) { println!("{:?}",slice); } for slice in v.iter().collect::<Vec<_>>().windows(2) { println!("{:?}",slice); }
有时最好的解决方案是最简单的.