在一些连续的容器上迭代大小为 N 的切片

Iterate slices of size N over some contiguous container

假设我们有一个点向量,写成整数的平面序列。向量的大小是精确的,我们想将其转换为 Point 结构的向量。所以我的转换目前看起来像这样。

#[derive(Debug)]
struct Point {
    x: i32,
    y: i32,
}
impl Point {
    fn new(x: i32, y : i32) -> Point {
        Point{x,y}
    }
}
impl From<Point> for String {
    fn from(point: Point) -> String {
        format!("({},{})", point.x, point.y)
    }
}

fn main() {
    let vec = vec![2,1,4,3,6,5]; // We want convert that
    let even = vec.iter().step_by(2);
    let odd = vec.iter().skip(1).step_by(2);
    let points: Vec<Point> 
                = even.zip(odd)
                .map(|(x,y)|Point::new(*x,*y))
                .collect();

    println!("{:?}", points);
}

工作起来很有魅力,直到我们想要添加 z 组件,并在每个循环中查看三个元素。我还没有从 docs 中找到任何合适的方法。那么,是否已经有一种通用的方法可以在 vector 上迭代一定大小的切片并将其解压缩到我的结构中,或者没有这样的方法,我应该自己实现这样的迭代器?它是使用一些较重的机器的信号,例如 serde.

我认为没有 pre-done 方法,但您可以轻松编写可以快速调整以包含第三个 z 组件的代码,类似于此(Playground):

#[derive(Debug, Default)]
struct PointBuilder {
    x: Option<i32>,
    y: Option<i32>,
    // add a z here
}

impl PointBuilder {
    fn add(&mut self, value: i32) {
        if self.x.is_none() {
            self.x = Some(value);
        } else if self.y.is_none() {
            self.y = Some(value);
        }
        // add a z here
    }

    fn try_build(&self) -> Option<Point> {
        // and one last z in this match expression
        match (self.x, self.y) {
            (Some(x), Some(y)) => Some(Point::new(x, y)),
            _ => None,
        }
    }
}

fn convert_to_points(data: impl IntoIterator<Item = i32>) -> Vec<Point> {
    data.into_iter()
        .fold((PointBuilder::default(), Vec::<Point>::new()), |(mut builder, mut points), value| {
                builder.add(value);
                if let Some(point) = builder.try_build() {
                    points.push(point);
                    (PointBuilder::default(), points)
                } else {
                    (builder, points)
                }
        })
        .1
}

fn main() {
    let vec = vec![2, 1, 4, 3, 6, 5]; // We want convert that
    let points = convert_to_points(vec);

    println!("{:?}", points);
}

这当然可以作为一个 proc-macro-derive 代码生成器来完成,如果你需要它用于许多结构,但我不知道任何库已经实现了这个,所以这取决于你的使用如果值得的话。

在 std 中使用 chunks_exact.

切片很容易做到
#[derive(Debug)]
struct Point {
    x: i32,
    y: i32,
    z: i32,
}
impl Point {
    fn new(x: i32, y : i32, z: i32) -> Point {
        Point{x,y, z}
    }
}

fn main() {
    let vec = vec![2,1,4,3,6,5];
    let points: Vec<Point> 
                = vec.chunks_exact(3)
                .map(|chunk|Point::new(chunk[0], chunk[1], chunk[2]))
                .collect();

    println!("{:?}", points);
}