1
1
use std:: cmp:: Ordering ;
2
2
use std:: fmt;
3
3
use std:: iter:: Fuse ;
4
- use std:: iter:: { FusedIterator , Peekable } ;
5
4
use std:: marker:: PhantomData ;
6
5
7
6
use either:: Either ;
@@ -12,19 +11,9 @@ use crate::size_hint::{self, SizeHint};
12
11
#[ cfg( doc) ]
13
12
use crate :: Itertools ;
14
13
15
- pub trait MergePredicate < T > {
16
- fn merge_pred ( & mut self , a : & T , b : & T ) -> bool ;
17
- }
18
-
19
14
#[ derive( Clone , Debug ) ]
20
15
pub struct MergeLte ;
21
16
22
- impl < T : PartialOrd > MergePredicate < T > for MergeLte {
23
- fn merge_pred ( & mut self , a : & T , b : & T ) -> bool {
24
- a <= b
25
- }
26
- }
27
-
28
17
/// An iterator adaptor that merges the two base iterators in ascending order.
29
18
/// If both base iterators are sorted (ascending), the result is sorted.
30
19
///
@@ -62,104 +51,21 @@ where
62
51
/// Iterator element type is `I::Item`.
63
52
///
64
53
/// See [`.merge_by()`](crate::Itertools::merge_by) for more information.
65
- #[ must_use = "iterator adaptors are lazy and do nothing unless consumed" ]
66
- pub struct MergeBy < I , J , F >
67
- where
68
- I : Iterator ,
69
- J : Iterator < Item = I :: Item > ,
70
- {
71
- a : Peekable < I > ,
72
- b : Peekable < J > ,
73
- fused : Option < bool > ,
74
- cmp : F ,
75
- }
76
-
77
- impl < I , J , F > fmt:: Debug for MergeBy < I , J , F >
78
- where
79
- I : Iterator + fmt:: Debug ,
80
- J : Iterator < Item = I :: Item > + fmt:: Debug ,
81
- I :: Item : fmt:: Debug ,
82
- {
83
- debug_fmt_fields ! ( MergeBy , a, b) ;
84
- }
85
-
86
- impl < T , F : FnMut ( & T , & T ) -> bool > MergePredicate < T > for F {
87
- fn merge_pred ( & mut self , a : & T , b : & T ) -> bool {
88
- self ( a, b)
89
- }
90
- }
54
+ pub type MergeBy < I , J , F > = InternalMergeJoinBy < I , J , F > ;
91
55
92
56
/// Create a `MergeBy` iterator.
93
57
pub fn merge_by_new < I , J , F > ( a : I , b : J , cmp : F ) -> MergeBy < I :: IntoIter , J :: IntoIter , F >
94
58
where
95
59
I : IntoIterator ,
96
60
J : IntoIterator < Item = I :: Item > ,
97
- F : MergePredicate < I :: Item > ,
98
61
{
99
- MergeBy {
100
- a : a. into_iter ( ) . peekable ( ) ,
101
- b : b. into_iter ( ) . peekable ( ) ,
102
- fused : None ,
103
- cmp,
104
- }
105
- }
106
-
107
- impl < I , J , F > Clone for MergeBy < I , J , F >
108
- where
109
- I : Iterator ,
110
- J : Iterator < Item = I :: Item > ,
111
- Peekable < I > : Clone ,
112
- Peekable < J > : Clone ,
113
- F : Clone ,
114
- {
115
- clone_fields ! ( a, b, fused, cmp) ;
116
- }
117
-
118
- impl < I , J , F > Iterator for MergeBy < I , J , F >
119
- where
120
- I : Iterator ,
121
- J : Iterator < Item = I :: Item > ,
122
- F : MergePredicate < I :: Item > ,
123
- {
124
- type Item = I :: Item ;
125
-
126
- fn next ( & mut self ) -> Option < Self :: Item > {
127
- let less_than = match self . fused {
128
- Some ( lt) => lt,
129
- None => match ( self . a . peek ( ) , self . b . peek ( ) ) {
130
- ( Some ( a) , Some ( b) ) => self . cmp . merge_pred ( a, b) ,
131
- ( Some ( _) , None ) => {
132
- self . fused = Some ( true ) ;
133
- true
134
- }
135
- ( None , Some ( _) ) => {
136
- self . fused = Some ( false ) ;
137
- false
138
- }
139
- ( None , None ) => return None ,
140
- } ,
141
- } ;
142
- if less_than {
143
- self . a . next ( )
144
- } else {
145
- self . b . next ( )
146
- }
147
- }
148
-
149
- fn size_hint ( & self ) -> ( usize , Option < usize > ) {
150
- // Not ExactSizeIterator because size may be larger than usize
151
- size_hint:: add ( self . a . size_hint ( ) , self . b . size_hint ( ) )
62
+ InternalMergeJoinBy {
63
+ left : put_back ( a. into_iter ( ) . fuse ( ) ) ,
64
+ right : put_back ( b. into_iter ( ) . fuse ( ) ) ,
65
+ cmp_fn : cmp,
152
66
}
153
67
}
154
68
155
- impl < I , J , F > FusedIterator for MergeBy < I , J , F >
156
- where
157
- I : FusedIterator ,
158
- J : FusedIterator < Item = I :: Item > ,
159
- F : MergePredicate < I :: Item > ,
160
- {
161
- }
162
-
163
69
/// Return an iterator adaptor that merge-joins items from the two base iterators in ascending order.
164
70
///
165
71
/// [`IntoIterator`] enabled version of [`Itertools::merge_join_by`].
@@ -269,6 +175,50 @@ impl<L, R, F: FnMut(&L, &R) -> bool> OrderingOrBool<L, R> for MergeFuncLR<F, boo
269
175
}
270
176
}
271
177
178
+ impl < T , F : FnMut ( & T , & T ) -> bool > OrderingOrBool < T , T > for F {
179
+ type Out = bool ;
180
+ type MergeResult = T ;
181
+ fn left ( left : T ) -> Self :: MergeResult {
182
+ left
183
+ }
184
+ fn right ( right : T ) -> Self :: MergeResult {
185
+ right
186
+ }
187
+ fn merge ( & mut self , left : T , right : T ) -> ( Option < T > , Option < T > , Self :: MergeResult ) {
188
+ if self ( & left, & right) {
189
+ ( None , Some ( right) , left)
190
+ } else {
191
+ ( Some ( left) , None , right)
192
+ }
193
+ }
194
+ fn size_hint ( left : SizeHint , right : SizeHint ) -> SizeHint {
195
+ // Not ExactSizeIterator because size may be larger than usize
196
+ size_hint:: add ( left, right)
197
+ }
198
+ }
199
+
200
+ impl < T : PartialOrd > OrderingOrBool < T , T > for MergeLte {
201
+ type Out = bool ;
202
+ type MergeResult = T ;
203
+ fn left ( left : T ) -> Self :: MergeResult {
204
+ left
205
+ }
206
+ fn right ( right : T ) -> Self :: MergeResult {
207
+ right
208
+ }
209
+ fn merge ( & mut self , left : T , right : T ) -> ( Option < T > , Option < T > , Self :: MergeResult ) {
210
+ if left <= right {
211
+ ( None , Some ( right) , left)
212
+ } else {
213
+ ( Some ( left) , None , right)
214
+ }
215
+ }
216
+ fn size_hint ( left : SizeHint , right : SizeHint ) -> SizeHint {
217
+ // Not ExactSizeIterator because size may be larger than usize
218
+ size_hint:: add ( left, right)
219
+ }
220
+ }
221
+
272
222
impl < I , J , F > Clone for InternalMergeJoinBy < I , J , F >
273
223
where
274
224
I : Iterator ,
0 commit comments