1+ use core:: hash:: BuildHasher ;
12use std:: collections:: hash_map:: Entry ;
2- use std:: collections:: { HashMap , HashSet } ;
3+ use std:: collections:: HashMap ;
34use std:: fmt;
4- use std:: hash:: Hash ;
5+ use std:: hash:: { Hash , RandomState } ;
56use std:: iter:: FusedIterator ;
67
78/// An iterator adapter to filter out duplicate elements.
89///
910/// See [`.unique_by()`](crate::Itertools::unique) for more information.
1011#[ derive( Clone ) ]
1112#[ must_use = "iterator adaptors are lazy and do nothing unless consumed" ]
12- pub struct UniqueBy < I : Iterator , V , F > {
13+ pub struct UniqueBy < I : Iterator , V , F , S = RandomState >
14+ where
15+ S : BuildHasher ,
16+ {
1317 iter : I ,
1418 // Use a Hashmap for the Entry API in order to prevent hashing twice.
1519 // This can maybe be replaced with a HashSet once `get_or_insert_with`
1620 // or a proper Entry API for Hashset is stable and meets this msrv
17- used : HashMap < V , ( ) > ,
21+ used : HashMap < V , ( ) , S > ,
1822 f : F ,
1923}
2024
21- impl < I , V , F > fmt:: Debug for UniqueBy < I , V , F >
25+ impl < I , V , F , S > fmt:: Debug for UniqueBy < I , V , F , S >
2226where
2327 I : Iterator + fmt:: Debug ,
2428 V : fmt:: Debug + Hash + Eq ,
29+ S : BuildHasher ,
2530{
2631 debug_fmt_fields ! ( UniqueBy , iter, used) ;
2732}
2833
2934/// Create a new `UniqueBy` iterator.
30- pub fn unique_by < I , V , F > ( iter : I , f : F ) -> UniqueBy < I , V , F >
35+ pub fn unique_by_with_hasher < I , V , F , S > ( iter : I , f : F , hash_builder : S ) -> UniqueBy < I , V , F , S >
3136where
3237 V : Eq + Hash ,
3338 F : FnMut ( & I :: Item ) -> V ,
3439 I : Iterator ,
40+ S : BuildHasher ,
3541{
3642 UniqueBy {
3743 iter,
38- used : HashMap :: new ( ) ,
44+ used : HashMap :: with_hasher ( hash_builder ) ,
3945 f,
4046 }
4147}
4248
4349// count the number of new unique keys in iterable (`used` is the set already seen)
44- fn count_new_keys < I , K > ( mut used : HashMap < K , ( ) > , iterable : I ) -> usize
50+ fn count_new_keys < I , K , S > ( mut used : HashMap < K , ( ) , S > , iterable : I ) -> usize
4551where
4652 I : IntoIterator < Item = K > ,
4753 K : Hash + Eq ,
54+ S : BuildHasher ,
4855{
4956 let iter = iterable. into_iter ( ) ;
5057 let current_used = used. len ( ) ;
5158 used. extend ( iter. map ( |key| ( key, ( ) ) ) ) ;
5259 used. len ( ) - current_used
5360}
5461
55- impl < I , V , F > Iterator for UniqueBy < I , V , F >
62+ impl < I , V , F , S > Iterator for UniqueBy < I , V , F , S >
5663where
5764 I : Iterator ,
5865 V : Eq + Hash ,
5966 F : FnMut ( & I :: Item ) -> V ,
67+ S : BuildHasher ,
6068{
6169 type Item = I :: Item ;
6270
@@ -77,30 +85,33 @@ where
7785 }
7886}
7987
80- impl < I , V , F > DoubleEndedIterator for UniqueBy < I , V , F >
88+ impl < I , V , F , S > DoubleEndedIterator for UniqueBy < I , V , F , S >
8189where
8290 I : DoubleEndedIterator ,
8391 V : Eq + Hash ,
8492 F : FnMut ( & I :: Item ) -> V ,
93+ S : BuildHasher ,
8594{
8695 fn next_back ( & mut self ) -> Option < Self :: Item > {
8796 let Self { iter, used, f } = self ;
8897 iter. rfind ( |v| used. insert ( f ( v) , ( ) ) . is_none ( ) )
8998 }
9099}
91100
92- impl < I , V , F > FusedIterator for UniqueBy < I , V , F >
101+ impl < I , V , F , S > FusedIterator for UniqueBy < I , V , F , S >
93102where
94103 I : FusedIterator ,
95104 V : Eq + Hash ,
96105 F : FnMut ( & I :: Item ) -> V ,
106+ S : BuildHasher ,
97107{
98108}
99109
100- impl < I > Iterator for Unique < I >
110+ impl < I , S > Iterator for Unique < I , S >
101111where
102112 I : Iterator ,
103113 I :: Item : Eq + Hash + Clone ,
114+ S : BuildHasher ,
104115{
105116 type Item = I :: Item ;
106117
@@ -127,10 +138,11 @@ where
127138 }
128139}
129140
130- impl < I > DoubleEndedIterator for Unique < I >
141+ impl < I , S > DoubleEndedIterator for Unique < I , S >
131142where
132143 I : DoubleEndedIterator ,
133144 I :: Item : Eq + Hash + Clone ,
145+ S : BuildHasher ,
134146{
135147 fn next_back ( & mut self ) -> Option < Self :: Item > {
136148 let UniqueBy { iter, used, .. } = & mut self . iter ;
@@ -145,10 +157,11 @@ where
145157 }
146158}
147159
148- impl < I > FusedIterator for Unique < I >
160+ impl < I , S > FusedIterator for Unique < I , S >
149161where
150162 I : FusedIterator ,
151163 I :: Item : Eq + Hash + Clone ,
164+ S : BuildHasher ,
152165{
153166}
154167
@@ -157,31 +170,34 @@ where
157170/// See [`.unique()`](crate::Itertools::unique) for more information.
158171#[ derive( Clone ) ]
159172#[ must_use = "iterator adaptors are lazy and do nothing unless consumed" ]
160- pub struct Unique < I >
173+ pub struct Unique < I , S = RandomState >
161174where
162175 I : Iterator ,
163176 I :: Item : Eq + Hash + Clone ,
177+ S : BuildHasher ,
164178{
165- iter : UniqueBy < I , I :: Item , ( ) > ,
179+ iter : UniqueBy < I , I :: Item , ( ) , S > ,
166180}
167181
168- impl < I > fmt:: Debug for Unique < I >
182+ impl < I , S > fmt:: Debug for Unique < I , S >
169183where
170184 I : Iterator + fmt:: Debug ,
171185 I :: Item : Hash + Eq + fmt:: Debug + Clone ,
186+ S : BuildHasher ,
172187{
173188 debug_fmt_fields ! ( Unique , iter) ;
174189}
175190
176- pub fn unique < I > ( iter : I ) -> Unique < I >
191+ pub fn unique_with_hasher < I , S > ( iter : I , hash_builder : S ) -> Unique < I , S >
177192where
178193 I : Iterator ,
179194 I :: Item : Eq + Hash + Clone ,
195+ S : BuildHasher ,
180196{
181197 Unique {
182198 iter : UniqueBy {
183199 iter,
184- used : HashMap :: new ( ) ,
200+ used : HashMap :: with_hasher ( hash_builder ) ,
185201 f : ( ) ,
186202 } ,
187203 }
0 commit comments