IntoIterator
The Iterator trait tells you how to iterate once you have created an iterator. The related trait IntoIterator defines how to create an iterator for a type. It is used automatically by the for loop.
1. struct Grid {
2. x_coords: Vec<u32>,
3. y_coords: Vec<u32>,
4. }
6. impl IntoIterator for Grid {
7. type Item = (u32, u32);
8. type IntoIter = GridIter;
9. fn into_iter(self) -> GridIter {
10. GridIter { grid: self, i: 0, j: 0 }
11. }
12. }
14. struct GridIter {
15. grid: Grid,
16. i: usize,
17. j: usize,
18. }
20. impl Iterator for GridIter {
21. type Item = (u32, u32);
23. fn next(&mut self) -> Option<(u32, u32)> {
24. if self.i >= self.grid.x_coords.len() {
25. self.i = 0;
26. self.j += 1;
27. if self.j >= self.grid.y_coords.len() {
28. return None;
29. }
30. }
31. let res = Some((self.grid.x_coords[self.i], self.grid.y_coords[self.j]));
32. self.i += 1;
33. res
34. }
35. }
37. fn main() {
38. let grid = Grid { x_coords: vec![3, 5, 7, 9], y_coords: vec![10, 20, 30, 40] };
39. for (x, y) in grid {
40. println!("point = {x}, {y}");
41. }
42. }
This slide should take about 5 minutes.
Click through to the docs for IntoIterator. Every implementation of IntoIterator must declare two types:
Item: the type to iterate over, such asi8,- “IntoIter”:“into_iter”方法返回的“Iterator”类型。
Note that IntoIter and Item are linked: the iterator must have the same Item type, which means that it returns Option<Item>
此示例对 x 坐标和 y 坐标的所有组合进行了迭代。
请尝试在 main 中对网格进行两次迭代。为什么会失败?请注意,IntoIterator::into_iter 获得了 self 的所有权。
如要解决此问题,请为 &Grid 实现 IntoIterator,并在 GridIter 中存储对 Grid 的引用。
对于标准库类型,可能会出现同样的问题:for e in some_vector 将获得 some_vector 的所有权,并迭代该矢量中的自有元素。请改用 for e in &some_vector 来迭代 some_vector 的元素的引用。
