使用chunks(或chunks_mut,如果您需要可变性):
fn main() {
let things = [5, 4, 3, 2, 1];
for slice in things.chunks(2) {
println!("{:?}", slice);
}
}
输出:
[5, 4]
[3, 2]
[1]
将其与Range 结合的最简单方法是首先将范围收集到Vec(取消对切片的引用):
fn main() {
let things: Vec<_> = (1..100).collect();
for slice in things.chunks(5) {
println!("{:?}", slice);
}
}
另一种纯迭代器解决方案是使用Itertools::chunks_lazy:
extern crate itertools;
use itertools::Itertools;
fn main() {
for chunk in &(1..100).chunks_lazy(5) {
for val in chunk {
print!("{}, ", val);
}
println!("");
}
}
这提出了一个类似的解决方案,只需要标准库:
fn main() {
let mut range = (1..100).peekable();
while range.peek().is_some() {
for value in range.by_ref().take(5) {
print!("{}, ", value);
}
println!("");
}
}
一个技巧是 Ruby 和 Rust 在这里有不同的处理方式,主要集中在效率上。
在 Ruby 中,Enumerable 可以创建新数组来填充值,而无需担心所有权并每次都返回一个新数组(请与 this_slice.object_id 核对)。
在 Rust 中,每次都分配一个新向量是非常不寻常的。此外,由于复杂的生命周期问题,您无法轻松返回对迭代器持有的向量的引用。
一个与 Ruby 非常相似的解决方案是:
fn main() {
let mut range = (1..100).peekable();
while range.peek().is_some() {
let chunk: Vec<_> = range.by_ref().take(5).collect();
println!("{:?}", chunk);
}
}
哪些可以被包裹在一个隐藏细节的新迭代器中:
use std::iter::Peekable;
struct InefficientChunks<I>
where I: Iterator
{
iter: Peekable<I>,
size: usize,
}
impl<I> Iterator for InefficientChunks<I>
where I: Iterator
{
type Item = Vec<I::Item>;
fn next(&mut self) -> Option<Self::Item> {
if self.iter.peek().is_some() {
Some(self.iter.by_ref().take(self.size).collect())
} else {
None
}
}
}
trait Awesome: Iterator + Sized {
fn inefficient_chunks(self, size: usize) -> InefficientChunks<Self> {
InefficientChunks {
iter: self.peekable(),
size: size,
}
}
}
impl<I> Awesome for I where I: Iterator {}
fn main() {
for chunk in (1..100).inefficient_chunks(5) {
println!("{:?}", chunk);
}
}