1
1
use alloc:: boxed:: Box ;
2
- use alloc :: vec :: Vec ;
2
+ use core :: array ;
3
3
use std:: fmt;
4
4
use std:: iter:: FusedIterator ;
5
5
6
6
use super :: lazy_buffer:: LazyBuffer ;
7
7
use crate :: adaptors:: checked_binomial;
8
-
8
+ use crate :: combinations :: PoolIndex ;
9
9
/// An iterator to iterate through all the `n`-length combinations in an iterator, with replacement.
10
10
///
11
11
/// See [`.combinations_with_replacement()`](crate::Itertools::combinations_with_replacement)
12
12
/// for more information.
13
13
#[ derive( Clone ) ]
14
14
#[ must_use = "iterator adaptors are lazy and do nothing unless consumed" ]
15
- pub struct CombinationsWithReplacement < I >
15
+ pub struct CombinationsWithReplacementGeneric < I , Idx >
16
16
where
17
17
I : Iterator ,
18
18
I :: Item : Clone ,
19
19
{
20
- indices : Box < [ usize ] > ,
20
+ indices : Idx ,
21
21
pool : LazyBuffer < I > ,
22
22
first : bool ,
23
23
}
24
24
25
- impl < I > fmt:: Debug for CombinationsWithReplacement < I >
25
+ /// Iterator for `Box<[I]>` valued combinations_with_replacement returned by [`.combinations_with_replacement()`](crate::Itertools::combinations_with_replacement)
26
+ pub type CombinationsWithReplacement < I > = CombinationsWithReplacementGeneric < I , Box < [ usize ] > > ;
27
+ impl < I , Idx > fmt:: Debug for CombinationsWithReplacementGeneric < I , Idx >
26
28
where
27
29
I : Iterator + fmt:: Debug ,
28
30
I :: Item : fmt:: Debug + Clone ,
31
+ Idx : fmt:: Debug ,
29
32
{
30
- debug_fmt_fields ! ( CombinationsWithReplacement , indices, pool, first) ;
33
+ debug_fmt_fields ! ( CombinationsWithReplacementGeneric , indices, pool, first) ;
31
34
}
32
35
33
36
/// Create a new `CombinationsWithReplacement` from a clonable iterator.
@@ -37,16 +40,11 @@ where
37
40
I :: Item : Clone ,
38
41
{
39
42
let indices = alloc:: vec![ 0 ; k] . into_boxed_slice ( ) ;
40
- let pool: LazyBuffer < I > = LazyBuffer :: new ( iter) ;
41
43
42
- CombinationsWithReplacement {
43
- indices,
44
- pool,
45
- first : true ,
46
- }
44
+ CombinationsWithReplacementGeneric :: new ( iter, indices)
47
45
}
48
46
49
- impl < I > CombinationsWithReplacement < I >
47
+ impl < I : Iterator , Idx : PoolIndex < I :: Item > > CombinationsWithReplacementGeneric < I , Idx >
50
48
where
51
49
I : Iterator ,
52
50
I :: Item : Clone ,
62
60
63
61
// Work out where we need to update our indices
64
62
let mut increment = None ;
65
- for ( i, indices_int) in self . indices . iter ( ) . enumerate ( ) . rev ( ) {
63
+ let indices: & mut [ usize ] = self . indices . borrow_mut ( ) ;
64
+ for ( i, indices_int) in indices. iter ( ) . enumerate ( ) . rev ( ) {
66
65
if * indices_int < self . pool . len ( ) - 1 {
67
66
increment = Some ( ( i, indices_int + 1 ) ) ;
68
67
break ;
@@ -73,39 +72,52 @@ where
73
72
Some ( ( increment_from, increment_value) ) => {
74
73
// We need to update the rightmost non-max value
75
74
// and all those to the right
76
- self . indices [ increment_from..] . fill ( increment_value) ;
75
+ indices[ increment_from..] . fill ( increment_value) ;
77
76
false
78
77
}
79
78
// Otherwise, we're done
80
79
None => true ,
81
80
}
82
81
}
82
+ /// Constructor with arguments the inner iterator and the initial state for the indices.
83
+ fn new ( iter : I , indices : Idx ) -> Self {
84
+ Self {
85
+ indices,
86
+ pool : LazyBuffer :: new ( iter) ,
87
+ first : true ,
88
+ }
89
+ }
83
90
}
84
91
85
- impl < I > Iterator for CombinationsWithReplacement < I >
92
+ impl < I , Idx > Iterator for CombinationsWithReplacementGeneric < I , Idx >
86
93
where
87
94
I : Iterator ,
88
95
I :: Item : Clone ,
96
+ Idx : PoolIndex < I :: Item > ,
89
97
{
90
- type Item = Vec < I :: Item > ;
98
+ type Item = Idx :: Item ;
91
99
92
100
fn next ( & mut self ) -> Option < Self :: Item > {
93
101
if self . first {
94
102
// In empty edge cases, stop iterating immediately
95
- if !( self . indices . is_empty ( ) || self . pool . get_next ( ) ) {
103
+ if !( core:: borrow:: Borrow :: < [ usize ] > :: borrow ( & self . indices ) . is_empty ( )
104
+ || self . pool . get_next ( ) )
105
+ {
96
106
return None ;
97
107
}
98
108
self . first = false ;
99
109
} else if self . increment_indices ( ) {
100
110
return None ;
101
111
}
102
- Some ( self . pool . get_at ( & self . indices ) )
112
+ Some ( self . indices . extract_item ( & self . pool ) )
103
113
}
104
114
105
115
fn nth ( & mut self , n : usize ) -> Option < Self :: Item > {
106
116
if self . first {
107
117
// In empty edge cases, stop iterating immediately
108
- if !( self . indices . is_empty ( ) || self . pool . get_next ( ) ) {
118
+ if !( core:: borrow:: Borrow :: < [ usize ] > :: borrow ( & self . indices ) . is_empty ( )
119
+ || self . pool . get_next ( ) )
120
+ {
109
121
return None ;
110
122
}
111
123
self . first = false ;
@@ -117,13 +129,13 @@ where
117
129
return None ;
118
130
}
119
131
}
120
- Some ( self . pool . get_at ( & self . indices ) )
132
+ Some ( self . indices . extract_item ( & self . pool ) )
121
133
}
122
134
123
135
fn size_hint ( & self ) -> ( usize , Option < usize > ) {
124
136
let ( mut low, mut upp) = self . pool . size_hint ( ) ;
125
- low = remaining_for ( low, self . first , & self . indices ) . unwrap_or ( usize:: MAX ) ;
126
- upp = upp. and_then ( |upp| remaining_for ( upp, self . first , & self . indices ) ) ;
137
+ low = remaining_for ( low, self . first , self . indices . borrow ( ) ) . unwrap_or ( usize:: MAX ) ;
138
+ upp = upp. and_then ( |upp| remaining_for ( upp, self . first , self . indices . borrow ( ) ) ) ;
127
139
( low, upp)
128
140
}
129
141
@@ -134,14 +146,15 @@ where
134
146
first,
135
147
} = self ;
136
148
let n = pool. count ( ) ;
137
- remaining_for ( n, first, & indices) . unwrap ( )
149
+ remaining_for ( n, first, indices. borrow ( ) ) . unwrap ( )
138
150
}
139
151
}
140
152
141
- impl < I > FusedIterator for CombinationsWithReplacement < I >
153
+ impl < I , Idx > FusedIterator for CombinationsWithReplacementGeneric < I , Idx >
142
154
where
143
155
I : Iterator ,
144
156
I :: Item : Clone ,
157
+ Idx : PoolIndex < I :: Item > ,
145
158
{
146
159
}
147
160
0 commit comments