@@ -710,18 +710,20 @@ where
710
710
///
711
711
/// ```
712
712
/// use hashbag::HashBag;
713
+ /// use std::collections::HashSet;
714
+ /// use std::iter::FromIterator;
713
715
///
714
716
/// let a: HashBag<_> = [1, 2, 3, 3].iter().cloned().collect();
715
717
/// let b: HashBag<_> = [2, 3].iter().cloned().collect();
716
- /// let expected: HashBag <_> = [ 1, 3].iter().cloned().collect( );
717
- /// let actual: HashBag <_> = a.difference(&b).cloned( ).collect();
718
+ /// let expected: HashSet <_> = HashSet::from_iter([(& 1, 1), (&3, 1)] );
719
+ /// let actual: HashSet <_> = a.difference(&b).collect();
718
720
/// assert_eq!(expected, actual);
719
721
/// ```
720
722
pub fn difference < ' a > ( & ' a self , other : & ' a HashBag < T , S > ) -> Difference < ' a , T , S > {
721
723
Difference {
722
- base_iter : self . iter ( ) ,
724
+ items : self . items . iter ( ) ,
723
725
other,
724
- removed_from_other : HashMap :: new ( ) ,
726
+ upper_bound : self . count ,
725
727
}
726
728
}
727
729
@@ -1136,21 +1138,20 @@ impl<'a, T> Iterator for Drain<'a, T> {
1136
1138
/// This `struct` is created by [`HashBag::difference`].
1137
1139
/// See its documentation for more.
1138
1140
pub struct Difference < ' a , T , S = RandomState > {
1139
- /// An iterator over " self"
1140
- base_iter : Iter < ' a , T > ,
1141
+ /// An iterator over ` self` items
1142
+ items : std :: collections :: hash_map :: Iter < ' a , T , usize > ,
1141
1143
1142
1144
/// The bag with entries we DO NOT want to return
1143
1145
other : & ' a HashBag < T , S > ,
1144
1146
1145
- /// Keeps track of many times we have conceptually "consumed" an entry from
1146
- /// `other`.
1147
- removed_from_other : HashMap < & ' a T , usize > ,
1147
+ /// For `size_hint()`
1148
+ upper_bound : usize ,
1148
1149
}
1149
1150
1150
1151
impl < ' a , T : fmt:: Debug > fmt:: Debug for Difference < ' a , T > {
1151
1152
fn fmt ( & self , fmt : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
1152
1153
fmt. debug_struct ( "Difference" )
1153
- . field ( "base_iter " , & self . base_iter )
1154
+ . field ( "items " , & self . items )
1154
1155
. field ( "other" , & self . other )
1155
1156
. finish ( )
1156
1157
}
@@ -1161,30 +1162,22 @@ where
1161
1162
T : Eq + Hash ,
1162
1163
S : BuildHasher ,
1163
1164
{
1164
- type Item = & ' a T ;
1165
+ type Item = ( & ' a T , usize ) ;
1165
1166
1166
1167
#[ inline]
1167
- fn next ( & mut self ) -> Option < & ' a T > {
1168
+ fn next ( & mut self ) -> Option < Self :: Item > {
1168
1169
loop {
1169
- let next = self . base_iter . next ( ) ?;
1170
- let removal_count = self . removed_from_other . entry ( next) . or_insert ( 0 ) ;
1171
-
1172
- // Keep track of how many times we have removed the current entry.
1173
- // We don't actually remove anything, we just pretend we do.
1174
- * removal_count += 1 ;
1175
-
1176
- // If we removed MORE entries from `other`, THEN we may start
1177
- // returning entries from the base iterator.
1178
- if * removal_count > self . other . contains ( next) {
1179
- return Some ( next) ;
1170
+ let ( t, n) = self . items . next ( ) ?;
1171
+ let other_n = self . other . contains ( t) ;
1172
+ if other_n < * n {
1173
+ return Some ( ( t, * n - other_n) ) ;
1180
1174
}
1181
1175
}
1182
1176
}
1183
1177
1184
1178
#[ inline]
1185
1179
fn size_hint ( & self ) -> ( usize , Option < usize > ) {
1186
- let ( _, upper_bound) = self . base_iter . size_hint ( ) ;
1187
- ( 0 , upper_bound)
1180
+ ( 0 , Some ( self . upper_bound ) )
1188
1181
}
1189
1182
}
1190
1183
@@ -1284,11 +1277,11 @@ mod tests {
1284
1277
let this = self_entries. iter ( ) . collect :: < HashBag < _ > > ( ) ;
1285
1278
let other = other_entries. iter ( ) . collect :: < HashBag < _ > > ( ) ;
1286
1279
let expected = expected_entries. iter ( ) . collect :: < HashBag < _ > > ( ) ;
1287
- assert_eq ! (
1288
- this. difference( & other)
1289
- . copied ( )
1290
- . collect :: < HashBag < & isize >> ( ) ,
1291
- expected
1292
- ) ;
1280
+ let mut actual = HashBag :: new ( ) ;
1281
+ for ( t , n ) in this. difference ( & other) {
1282
+ actual . insert_many ( * t , n ) ;
1283
+ }
1284
+
1285
+ assert_eq ! ( actual , expected ) ;
1293
1286
}
1294
1287
}
0 commit comments