如何在Rust中用迭代器实现数组i与i+1位置元素的特定元组遍历?
使用Rust迭代器替代for循环收集相邻元素元组
我在Rust Playground中编写了一个示例代码,用来遍历Person数组,收集索引i处Person的firstname与索引i+1处Person的surname组成的元组。当前通过for循环可以实现这个功能,但我希望改用iter()迭代器来实现,方便后续使用collect()或fold等方法,而非使用for循环。请问该如何实现?
原代码如下:
#[derive(Clone)] pub struct Person { pub firstname: Vec<u8>, pub surname: Vec<u8>, } fn main() { let p0 = Person { firstname: vec![0u8; 5], surname: vec![1u8; 5], }; let p1 = Person { firstname: vec![2u8; 7], surname: vec![3u8; 2], }; let p2 = Person { firstname: vec![4u8; 8], surname: vec![5u8; 8], }; let p3 = Person { firstname: vec![6u8; 3], surname: vec![7u8; 1], }; let people = [p0, p1, p2, p3]; for i in 0..people.len() { if i + 1 < people.len() { println!( "{:?}", (people[i].firstname.clone(), people[i + 1].surname.clone()) ) } } }
方法一:使用windows(2)获取相邻元素窗口
Rust的切片迭代器提供了windows(n)方法,它会返回一个迭代器,每次生成包含n个连续元素的不可变切片。对于你的需求,我们可以用windows(2)来获取每一对相邻的Person元素,然后从切片中取出第一个元素的firstname和第二个元素的surname:
#[derive(Clone)] pub struct Person { pub firstname: Vec<u8>, pub surname: Vec<u8>, } fn main() { let p0 = Person { firstname: vec![0u8; 5], surname: vec![1u8; 5], }; let p1 = Person { firstname: vec![2u8; 7], surname: vec![3u8; 2], }; let p2 = Person { firstname: vec![4u8; 8], surname: vec![5u8; 8], }; let p3 = Person { firstname: vec![6u8; 3], surname: vec![7u8; 1], }; let people = [p0, p1, p2, p3]; // 使用windows(2)遍历相邻元素对 let tuples = people.windows(2) .map(|window| { // window是&[Person; 2]类型,取出第一个和第二个元素 (window[0].firstname.clone(), window[1].surname.clone()) }) .collect::<Vec<_>>(); // 打印结果,和原for循环一致 for tuple in tuples { println!("{:?}", tuple); } }
这种方法的优势是语义非常清晰,直接表达“处理每一组相邻的2个元素”,适合需要处理连续多个元素的场景。
方法二:使用zip配对原迭代器与跳过首元素的迭代器
另一种方式是将原数组的迭代器和跳过第一个元素的迭代器进行zip操作,这样每一对元素就是原数组中索引i和i+1的元素:
#[derive(Clone)] pub struct Person { pub firstname: Vec<u8>, pub surname: Vec<u8>, } fn main() { let p0 = Person { firstname: vec![0u8; 5], surname: vec![1u8; 5], }; let p1 = Person { firstname: vec![2u8; 7], surname: vec![3u8; 2], }; let p2 = Person { firstname: vec![4u8; 8], surname: vec![5u8; 8], }; let p3 = Person { firstname: vec![6u8; 3], surname: vec![7u8; 1], }; let people = [p0, p1, p2, p3]; // 配对原迭代器和跳过第一个元素的迭代器 let tuples = people.iter() .zip(people.iter().skip(1)) .map(|(prev, next)| { (prev.firstname.clone(), next.surname.clone()) }) .collect::<Vec<_>>(); // 打印结果 for tuple in tuples { println!("{:?}", tuple); } }
这种方法更灵活,如果你需要对i和i+k的元素进行配对,只需要调整skip(k)的参数即可。
两种方法都可以完美替代原有的for循环,并且支持后续链式调用collect()、fold()等迭代器方法,完全符合你的需求。
内容的提问来源于stack exchange,提问作者Ziva
相关产品推荐
相关产品推荐

