@@ -2,19 +2,23 @@ use std::cmp::Ordering;
22use std:: iter:: Fuse ;
33use std:: fmt;
44
5+ use either:: Either ;
6+
57use super :: adaptors:: { PutBack , put_back} ;
68use crate :: either_or_both:: EitherOrBoth ;
9+ use crate :: size_hint:: { self , SizeHint } ;
710#[ cfg( doc) ]
811use crate :: Itertools ;
912
1013/// Return an iterator adaptor that merge-joins items from the two base iterators in ascending order.
1114///
1215/// [`IntoIterator`] enabled version of [`Itertools::merge_join_by`].
13- pub fn merge_join_by < I , J , F > ( left : I , right : J , cmp_fn : F )
16+ pub fn merge_join_by < I , J , F , T > ( left : I , right : J , cmp_fn : F )
1417 -> MergeJoinBy < I :: IntoIter , J :: IntoIter , F >
1518 where I : IntoIterator ,
1619 J : IntoIterator ,
17- F : FnMut ( & I :: Item , & J :: Item ) -> Ordering
20+ F : FnMut ( & I :: Item , & J :: Item ) -> T ,
21+ T : OrderingOrBool < I :: Item , J :: Item > ,
1822{
1923 MergeJoinBy {
2024 left : put_back ( left. into_iter ( ) . fuse ( ) ) ,
@@ -30,7 +34,66 @@ pub fn merge_join_by<I, J, F>(left: I, right: J, cmp_fn: F)
3034pub struct MergeJoinBy < I : Iterator , J : Iterator , F > {
3135 left : PutBack < Fuse < I > > ,
3236 right : PutBack < Fuse < J > > ,
33- cmp_fn : F
37+ cmp_fn : F ,
38+ }
39+
40+ pub trait OrderingOrBool < L , R > {
41+ type MergeResult ;
42+ fn left ( left : L ) -> Self :: MergeResult ;
43+ fn right ( right : R ) -> Self :: MergeResult ;
44+ // "merge" never returns (Some(...), Some(...), ...) so Option<Either<I::Item, J::Item>>
45+ // is appealing but it is always followed by two put_backs, so we think the compiler is
46+ // smart enough to optimize it. Or we could move put_backs into "merge".
47+ fn merge ( self , left : L , right : R ) -> ( Option < L > , Option < R > , Self :: MergeResult ) ;
48+ fn size_hint ( left : SizeHint , right : SizeHint ) -> SizeHint ;
49+ }
50+
51+ impl < L , R > OrderingOrBool < L , R > for Ordering {
52+ type MergeResult = EitherOrBoth < L , R > ;
53+ fn left ( left : L ) -> Self :: MergeResult {
54+ EitherOrBoth :: Left ( left)
55+ }
56+ fn right ( right : R ) -> Self :: MergeResult {
57+ EitherOrBoth :: Right ( right)
58+ }
59+ fn merge ( self , left : L , right : R ) -> ( Option < L > , Option < R > , Self :: MergeResult ) {
60+ match self {
61+ Ordering :: Equal => ( None , None , EitherOrBoth :: Both ( left, right) ) ,
62+ Ordering :: Less => ( None , Some ( right) , EitherOrBoth :: Left ( left) ) ,
63+ Ordering :: Greater => ( Some ( left) , None , EitherOrBoth :: Right ( right) ) ,
64+ }
65+ }
66+ fn size_hint ( left : SizeHint , right : SizeHint ) -> SizeHint {
67+ let ( a_lower, a_upper) = left;
68+ let ( b_lower, b_upper) = right;
69+ let lower = :: std:: cmp:: max ( a_lower, b_lower) ;
70+ let upper = match ( a_upper, b_upper) {
71+ ( Some ( x) , Some ( y) ) => x. checked_add ( y) ,
72+ _ => None ,
73+ } ;
74+ ( lower, upper)
75+ }
76+ }
77+
78+ impl < L , R > OrderingOrBool < L , R > for bool {
79+ type MergeResult = Either < L , R > ;
80+ fn left ( left : L ) -> Self :: MergeResult {
81+ Either :: Left ( left)
82+ }
83+ fn right ( right : R ) -> Self :: MergeResult {
84+ Either :: Right ( right)
85+ }
86+ fn merge ( self , left : L , right : R ) -> ( Option < L > , Option < R > , Self :: MergeResult ) {
87+ if self {
88+ ( None , Some ( right) , Either :: Left ( left) )
89+ } else {
90+ ( Some ( left) , None , Either :: Right ( right) )
91+ }
92+ }
93+ fn size_hint ( left : SizeHint , right : SizeHint ) -> SizeHint {
94+ // Not ExactSizeIterator because size may be larger than usize
95+ size_hint:: add ( left, right)
96+ }
3497}
3598
3699impl < I , J , F > Clone for MergeJoinBy < I , J , F >
@@ -52,49 +115,34 @@ impl<I, J, F> fmt::Debug for MergeJoinBy<I, J, F>
52115 debug_fmt_fields ! ( MergeJoinBy , left, right) ;
53116}
54117
55- impl < I , J , F > Iterator for MergeJoinBy < I , J , F >
118+ impl < I , J , F , T > Iterator for MergeJoinBy < I , J , F >
56119 where I : Iterator ,
57120 J : Iterator ,
58- F : FnMut ( & I :: Item , & J :: Item ) -> Ordering
121+ F : FnMut ( & I :: Item , & J :: Item ) -> T ,
122+ T : OrderingOrBool < I :: Item , J :: Item > ,
59123{
60- type Item = EitherOrBoth < I :: Item , J :: Item > ;
124+ type Item = T :: MergeResult ;
61125
62126 fn next ( & mut self ) -> Option < Self :: Item > {
63127 match ( self . left . next ( ) , self . right . next ( ) ) {
64128 ( None , None ) => None ,
65- ( Some ( left) , None ) =>
66- Some ( EitherOrBoth :: Left ( left) ) ,
67- ( None , Some ( right) ) =>
68- Some ( EitherOrBoth :: Right ( right) ) ,
129+ ( Some ( left) , None ) => Some ( T :: left ( left) ) ,
130+ ( None , Some ( right) ) => Some ( T :: right ( right) ) ,
69131 ( Some ( left) , Some ( right) ) => {
70- match ( self . cmp_fn ) ( & left, & right) {
71- Ordering :: Equal =>
72- Some ( EitherOrBoth :: Both ( left, right) ) ,
73- Ordering :: Less => {
74- self . right . put_back ( right) ;
75- Some ( EitherOrBoth :: Left ( left) )
76- } ,
77- Ordering :: Greater => {
78- self . left . put_back ( left) ;
79- Some ( EitherOrBoth :: Right ( right) )
80- }
132+ let ( left, right, next) = ( self . cmp_fn ) ( & left, & right) . merge ( left, right) ;
133+ if let Some ( left) = left {
134+ self . left . put_back ( left) ;
135+ }
136+ if let Some ( right) = right {
137+ self . right . put_back ( right) ;
81138 }
139+ Some ( next)
82140 }
83141 }
84142 }
85143
86- fn size_hint ( & self ) -> ( usize , Option < usize > ) {
87- let ( a_lower, a_upper) = self . left . size_hint ( ) ;
88- let ( b_lower, b_upper) = self . right . size_hint ( ) ;
89-
90- let lower = :: std:: cmp:: max ( a_lower, b_lower) ;
91-
92- let upper = match ( a_upper, b_upper) {
93- ( Some ( x) , Some ( y) ) => x. checked_add ( y) ,
94- _ => None ,
95- } ;
96-
97- ( lower, upper)
144+ fn size_hint ( & self ) -> SizeHint {
145+ T :: size_hint ( self . left . size_hint ( ) , self . right . size_hint ( ) )
98146 }
99147
100148 fn count ( mut self ) -> usize {
@@ -106,10 +154,12 @@ impl<I, J, F> Iterator for MergeJoinBy<I, J, F>
106154 ( None , Some ( _right) ) => break count + 1 + self . right . into_parts ( ) . 1 . count ( ) ,
107155 ( Some ( left) , Some ( right) ) => {
108156 count += 1 ;
109- match ( self . cmp_fn ) ( & left, & right) {
110- Ordering :: Equal => { }
111- Ordering :: Less => self . right . put_back ( right) ,
112- Ordering :: Greater => self . left . put_back ( left) ,
157+ let ( left, right, _) = ( self . cmp_fn ) ( & left, & right) . merge ( left, right) ;
158+ if let Some ( left) = left {
159+ self . left . put_back ( left) ;
160+ }
161+ if let Some ( right) = right {
162+ self . right . put_back ( right) ;
113163 }
114164 }
115165 }
@@ -122,27 +172,24 @@ impl<I, J, F> Iterator for MergeJoinBy<I, J, F>
122172 match ( self . left . next ( ) , self . right . next ( ) ) {
123173 ( None , None ) => break previous_element,
124174 ( Some ( left) , None ) => {
125- break Some ( EitherOrBoth :: Left (
175+ break Some ( T :: left (
126176 self . left . into_parts ( ) . 1 . last ( ) . unwrap_or ( left) ,
127177 ) )
128178 }
129179 ( None , Some ( right) ) => {
130- break Some ( EitherOrBoth :: Right (
180+ break Some ( T :: right (
131181 self . right . into_parts ( ) . 1 . last ( ) . unwrap_or ( right) ,
132182 ) )
133183 }
134184 ( Some ( left) , Some ( right) ) => {
135- previous_element = match ( self . cmp_fn ) ( & left, & right) {
136- Ordering :: Equal => Some ( EitherOrBoth :: Both ( left, right) ) ,
137- Ordering :: Less => {
138- self . right . put_back ( right) ;
139- Some ( EitherOrBoth :: Left ( left) )
140- }
141- Ordering :: Greater => {
142- self . left . put_back ( left) ;
143- Some ( EitherOrBoth :: Right ( right) )
144- }
185+ let ( left, right, elem) = ( self . cmp_fn ) ( & left, & right) . merge ( left, right) ;
186+ if let Some ( left) = left {
187+ self . left . put_back ( left) ;
188+ }
189+ if let Some ( right) = right {
190+ self . right . put_back ( right) ;
145191 }
192+ previous_element = Some ( elem) ;
146193 }
147194 }
148195 }
@@ -156,13 +203,17 @@ impl<I, J, F> Iterator for MergeJoinBy<I, J, F>
156203 n -= 1 ;
157204 match ( self . left . next ( ) , self . right . next ( ) ) {
158205 ( None , None ) => break None ,
159- ( Some ( _left) , None ) => break self . left . nth ( n) . map ( EitherOrBoth :: Left ) ,
160- ( None , Some ( _right) ) => break self . right . nth ( n) . map ( EitherOrBoth :: Right ) ,
161- ( Some ( left) , Some ( right) ) => match ( self . cmp_fn ) ( & left, & right) {
162- Ordering :: Equal => { }
163- Ordering :: Less => self . right . put_back ( right) ,
164- Ordering :: Greater => self . left . put_back ( left) ,
165- } ,
206+ ( Some ( _left) , None ) => break self . left . nth ( n) . map ( T :: left) ,
207+ ( None , Some ( _right) ) => break self . right . nth ( n) . map ( T :: right) ,
208+ ( Some ( left) , Some ( right) ) => {
209+ let ( left, right, _) = ( self . cmp_fn ) ( & left, & right) . merge ( left, right) ;
210+ if let Some ( left) = left {
211+ self . left . put_back ( left) ;
212+ }
213+ if let Some ( right) = right {
214+ self . right . put_back ( right) ;
215+ }
216+ }
166217 }
167218 }
168219 }
0 commit comments