在一些连续的容器上迭代大小为 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);
}
假设我们有一个点向量,写成整数的平面序列。向量的大小是精确的,我们想将其转换为 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);
}