1
1
use alloc:: vec:: Vec ;
2
2
use std:: fmt;
3
3
4
- /// Pseudo-iterator owned by [`CartesianPower`],
5
- /// yielding underlying indices by references to itself,
6
- /// the [streaming iterator](https://docs.rs/streaming-iterator/latest/streaming_iterator/) way.
4
+ /// Yield all indices combinations of size `pow` from `0..base`.
5
+ /// This "lending" iterator only allocates once,
6
+ /// and yields references to its internal owned slice of updated indices.
7
+ /// See [streaming iterator](https://docs.rs/streaming-iterator/latest/streaming_iterator/).
8
+ ///
9
+ /// The resulting iterator is "cycling",
10
+ /// meaning that, after the last `.next()` call has yielded `None`,
11
+ /// you can call `.next()` again to resume iteration from the start,
12
+ /// as many times as needed.
13
+ ///
14
+ /// This is the iterator internally used by [`CartesianPower`],
15
+ /// ```
16
+ /// use itertools::CartesianPowerIndices;
17
+ ///
18
+ /// let mut it = CartesianPowerIndices::new(3, 2);
19
+ /// assert_eq!(it.next(), Some(&[0, 0][..]));
20
+ /// assert_eq!(it.next(), Some(&[0, 1][..]));
21
+ /// assert_eq!(it.next(), Some(&[0, 2][..]));
22
+ /// assert_eq!(it.next(), Some(&[1, 0][..]));
23
+ /// assert_eq!(it.next(), Some(&[1, 1][..]));
24
+ /// assert_eq!(it.next(), Some(&[1, 2][..]));
25
+ /// assert_eq!(it.next(), Some(&[2, 0][..]));
26
+ /// assert_eq!(it.next(), Some(&[2, 1][..]));
27
+ /// assert_eq!(it.next(), Some(&[2, 2][..]));
28
+ /// assert_eq!(it.next(), None); // End of iteration.
29
+ /// assert_eq!(it.next(), Some(&[0, 0][..])); // Cycle: start over, forever.
30
+ /// assert_eq!(it.next(), Some(&[0, 1][..]));
31
+ /// // ...
32
+ ///
33
+ /// let mut it = CartesianPowerIndices::new(2, 3);
34
+ /// assert_eq!(it.next(), Some(&[0, 0, 0][..]));
35
+ /// assert_eq!(it.next(), Some(&[0, 0, 1][..]));
36
+ /// assert_eq!(it.next(), Some(&[0, 1, 0][..]));
37
+ /// assert_eq!(it.next(), Some(&[0, 1, 1][..]));
38
+ /// assert_eq!(it.next(), Some(&[1, 0, 0][..]));
39
+ /// assert_eq!(it.next(), Some(&[1, 0, 1][..]));
40
+ /// assert_eq!(it.next(), Some(&[1, 1, 0][..]));
41
+ /// assert_eq!(it.next(), Some(&[1, 1, 1][..]));
42
+ /// assert_eq!(it.next(), None);
43
+ /// assert_eq!(it.next(), Some(&[0, 0, 0][..]));
44
+ /// assert_eq!(it.next(), Some(&[0, 0, 1][..]));
45
+ /// // ...
46
+ /// ```
7
47
#[ derive( Debug , Clone ) ]
8
48
pub struct Indices {
9
49
// May be incremented by owner on first pass as long as exact value is unknown.
@@ -21,13 +61,18 @@ pub struct Indices {
21
61
}
22
62
23
63
impl Indices {
64
+ /// Create a new `base^pow` lending iterator.
24
65
pub fn new ( base : usize , pow : u32 ) -> Self {
25
66
Self {
26
67
base,
27
68
pow,
28
69
values : None ,
29
70
}
30
71
}
72
+
73
+ /// Step the iterator, yielding a reference to internal updated indices,
74
+ /// or `None` if the iteration is exhausted.
75
+ #[ allow( clippy:: should_implement_trait) ] // <- Intended `.next` name "like Iterator::next".
31
76
pub fn next ( & mut self ) -> Option < & [ usize ] > {
32
77
let Self { base, pow, values } = self ;
33
78
@@ -67,6 +112,25 @@ impl Indices {
67
112
}
68
113
}
69
114
115
+ /// Same as [`next`][crate::CartesianPowerIndices::next],
116
+ /// but skip `n` steps.
117
+ /// Return `None` if this would lead to iterator exhaustion.
118
+ /// Saturates in case of overflow:
119
+ /// the iterator is cycling,
120
+ /// but if you skip past the last iteration,
121
+ /// you'll obtain `None` no matter how far you skip.
122
+ /// Iteration will only resume on further calls to `.next()` and `.nth()`.
123
+ ///
124
+ /// ```
125
+ /// use itertools::CartesianPowerIndices;
126
+ ///
127
+ /// let mut it = CartesianPowerIndices::new(3, 2);
128
+ /// assert_eq!(it.nth(0), Some(&[0, 0][..]));
129
+ /// assert_eq!(it.nth(1), Some(&[0, 2][..]));
130
+ /// assert_eq!(it.nth(2), Some(&[1, 2][..]));
131
+ /// assert_eq!(it.nth(9), None); // Overshoot, but don't resume cycling yet.
132
+ /// assert_eq!(it.nth(2), Some(&[0, 2][..])); // Only resume cycling now.
133
+ /// ```
70
134
pub fn nth ( & mut self , n : usize ) -> Option < & [ usize ] > {
71
135
let Self { base, pow, values } = self ;
72
136
match ( base, pow, values, n) {
@@ -110,7 +174,8 @@ impl Indices {
110
174
}
111
175
}
112
176
113
- fn size_hint ( & self ) -> ( usize , Option < usize > ) {
177
+ /// Akin to [`Iterator::size_hint`].
178
+ pub fn size_hint ( & self ) -> ( usize , Option < usize > ) {
114
179
self . size_hint_with_base ( self . base )
115
180
}
116
181
@@ -195,11 +260,12 @@ fn inbounds_increment_by(n: usize, indices: &mut [usize], base: usize) -> bool {
195
260
false
196
261
}
197
262
198
- /// An adaptor iterating through all the ordered `n`-length lists of items
199
- /// yielded by the underlying iterator, including repetitions.
200
- /// Works by cloning the items into a fresh Vector on every `.next()`.
201
- /// If this is too much allocation for you,
202
- /// consider using the underlying lending [`Indices`] iterator instead.
263
+ /// The adaptor adaptor yielded by
264
+ /// [`.cartesian_power()`](crate::Itertools::cartesian_power).
265
+ ///
266
+ /// This iterator is *cycling*,
267
+ /// meaning that, once consumed after `.next()` returns `None`,
268
+ /// you can call `.next()` again to resume iteration from the start.
203
269
///
204
270
/// See [`.cartesian_power()`](crate::Itertools::cartesian_power)
205
271
/// for more information.
@@ -217,24 +283,19 @@ where
217
283
indices : Indices ,
218
284
}
219
285
220
- /// Create a new `CartesianPower` from an iterator of clonables.
221
- pub fn cartesian_power < I > ( iter : I , pow : u32 ) -> CartesianPower < I >
286
+ impl < I > CartesianPower < I >
222
287
where
223
288
I : Iterator ,
224
289
I :: Item : Clone ,
225
290
{
226
- CartesianPower {
227
- iter : Some ( iter) ,
228
- items : None ,
229
- indices : Indices :: new ( 0 , pow) ,
291
+ pub ( crate ) fn new ( iter : I , pow : u32 ) -> CartesianPower < I > {
292
+ CartesianPower {
293
+ iter : Some ( iter) ,
294
+ items : None ,
295
+ indices : Indices :: new ( 0 , pow) ,
296
+ }
230
297
}
231
- }
232
298
233
- impl < I > CartesianPower < I >
234
- where
235
- I : Iterator ,
236
- I :: Item : Clone ,
237
- {
238
299
/// Increments internal indices to advance to the next list to be yielded.
239
300
/// This collects new items from the underlying iterator
240
301
/// if they were not all already collected.
@@ -849,4 +910,19 @@ mod tests {
849
910
check ! ( "abc" , 3 => 27 o 27 o 27 o 27 o) ;
850
911
check ! ( "abc" , 3 => 28 o 28 o 28 o 28 o) ;
851
912
}
913
+
914
+ #[ test]
915
+ fn f ( ) {
916
+ use crate :: CartesianPowerIndices ;
917
+ let mut it = CartesianPowerIndices :: new ( 3 , 2 ) ;
918
+ while let Some ( indices) = it. next ( ) {
919
+ println ! ( "&{indices:?}" ) ;
920
+ }
921
+
922
+ let mut it = CartesianPowerIndices :: new ( 2 , 3 ) ;
923
+ while let Some ( indices) = it. next ( ) {
924
+ println ! ( "&{indices:?}" ) ;
925
+ }
926
+ panic ! ( "STOP HERE" ) ;
927
+ }
852
928
}
0 commit comments