diff --git a/src/lib.rs b/src/lib.rs index da5d835..85a9817 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -835,7 +835,7 @@ impl Grid { /// *i += 1; /// println!("value at row {row} and column {col} is: {i}"); /// } - /// + /// /// assert_eq!(grid[(0, 0)], 2); /// assert_eq!(grid[(0, 1)], 3); /// assert_eq!(grid[(1, 0)], 4); @@ -1444,7 +1444,8 @@ impl Grid { pub fn iter_rows(&self) -> GridRowIter<'_, T> { GridRowIter { grid: self, - row_index: 0, + row_start_index: 0, + row_end_index: self.rows, } } @@ -1466,7 +1467,8 @@ impl Grid { pub fn iter_cols(&self) -> GridColIter<'_, T> { GridColIter { grid: self, - col_index: 0, + col_start_index: 0, + col_end_index: self.cols, } } } @@ -1649,27 +1651,46 @@ impl From<(&Vec, &usize)> for Grid { #[derive(Clone)] pub struct GridRowIter<'a, T> { grid: &'a Grid, - row_index: usize, + row_start_index: usize, + row_end_index: usize, } + #[derive(Clone)] pub struct GridColIter<'a, T> { grid: &'a Grid, - col_index: usize, + col_start_index: usize, + col_end_index: usize, } impl<'a, T> Iterator for GridRowIter<'a, T> { type Item = StepBy>; fn next(&mut self) -> Option { - let rows = self.grid.rows(); - let row_index = self.row_index; + if self.row_start_index >= self.row_end_index { + return None; + } + + let row_iter = self.grid.iter_row(self.row_start_index); + self.row_start_index += 1; + Some(row_iter) + } - if !(0..rows).contains(&row_index) { + fn size_hint(&self) -> (usize, Option) { + let size = self.row_end_index - self.row_start_index; + (size, Some(size)) + } +} + +impl<'a, T> ExactSizeIterator for GridRowIter<'a, T> {} + +impl<'a, T> DoubleEndedIterator for GridRowIter<'a, T> { + fn next_back(&mut self) -> Option { + if self.row_start_index >= self.row_end_index { return None; } - let row_iter = self.grid.iter_row(row_index); - self.row_index += 1; + let row_iter = self.grid.iter_row(self.row_end_index - 1); + self.row_end_index -= 1; Some(row_iter) } } @@ -1678,16 +1699,32 @@ impl<'a, T> Iterator for GridColIter<'a, T> { type Item = StepBy>; fn next(&mut self) -> Option { - let cols = self.grid.cols(); - let col_index = self.col_index; + if self.col_start_index >= self.col_end_index { + return None; + } - if !(0..cols).contains(&col_index) { + let col_iter = self.grid.iter_col(self.col_start_index); + self.col_start_index += 1; + Some(col_iter) + } + + fn size_hint(&self) -> (usize, Option) { + let size = self.col_end_index - self.col_start_index; + (size, Some(size)) + } +} + +impl<'a, T> ExactSizeIterator for GridColIter<'a, T> {} + +impl<'a, T> DoubleEndedIterator for GridColIter<'a, T> { + fn next_back(&mut self) -> Option { + if self.col_start_index >= self.col_end_index { return None; } - let row_iter = self.grid.iter_col(col_index); - self.col_index += 1; - Some(row_iter) + let col_iter = self.grid.iter_col(self.col_end_index - 1); + self.col_end_index -= 1; + Some(col_iter) } } @@ -3108,6 +3145,34 @@ mod test { assert_eq!(sum_by_row, vec![1 + 2 + 3, 4 + 5 + 6]); } + #[test] + #[allow(clippy::redundant_closure_for_method_calls)] + fn iter_rows_rev() { + let grid: Grid = grid![[1,2,3][4,5,6]]; + let max_by_row: Vec = grid + .iter_rows() + .rev() + .map(|row| row.max().unwrap()) + .copied() + .collect(); + assert_eq!(max_by_row, vec![6, 3]); + + let sum_by_row: Vec = grid.iter_rows().rev().map(|row| row.sum()).collect(); + assert_eq!(sum_by_row, vec![4 + 5 + 6, 1 + 2 + 3]); + } + + #[test] + fn iter_rows_exact_size() { + let grid: Grid = grid![[1,2,3][4,5,6]]; + let mut row_iter = grid.iter_rows(); + assert_eq!(row_iter.len(), 2); + assert!(row_iter.next().is_some()); + assert_eq!(row_iter.len(), 1); + assert!(row_iter.next().is_some()); + assert_eq!(row_iter.len(), 0); + assert!(row_iter.next().is_none()); + } + #[test] #[allow(clippy::redundant_closure_for_method_calls)] fn iter_cols() { @@ -3124,6 +3189,37 @@ mod test { assert_eq!(sum_by_col, vec![1 + 4, 2 + 5, 3 + 6]); } + #[test] + #[allow(clippy::redundant_closure_for_method_calls)] + fn iter_cols_rev() { + let grid: Grid = grid![[1,2,3][4,5,6]]; + let max_by_col: Vec = grid + .iter_cols() + .rev() + .map(|col| col.max().unwrap()) + .copied() + .collect(); + + assert_eq!(max_by_col, vec![6, 5, 4]); + + let sum_by_col: Vec = grid.iter_cols().rev().map(|row| row.sum()).collect(); + assert_eq!(sum_by_col, vec![3 + 6, 2 + 5, 1 + 4]); + } + + #[test] + fn iter_cols_exact_size() { + let grid: Grid = grid![[1,2,3][4,5,6]]; + let mut col_iter = grid.iter_cols(); + assert_eq!(col_iter.len(), 3); + assert!(col_iter.next().is_some()); + assert_eq!(col_iter.len(), 2); + assert!(col_iter.next().is_some()); + assert_eq!(col_iter.len(), 1); + assert!(col_iter.next().is_some()); + assert_eq!(col_iter.len(), 0); + assert!(col_iter.next().is_none()); + } + #[test] fn remove_row() { let mut grid = grid![[1,2][3,4][5,6]];