1
+ use core:: hash:: BuildHasher ;
1
2
use std:: collections:: hash_map:: Entry ;
2
- use std:: collections:: { HashMap , HashSet } ;
3
+ use std:: collections:: HashMap ;
3
4
use std:: fmt;
4
- use std:: hash:: Hash ;
5
+ use std:: hash:: { Hash , RandomState } ;
5
6
use std:: iter:: FusedIterator ;
6
7
7
8
/// An iterator adapter to filter out duplicate elements.
8
9
///
9
10
/// See [`.unique_by()`](crate::Itertools::unique) for more information.
10
11
#[ derive( Clone ) ]
11
12
#[ 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
+ {
13
17
iter : I ,
14
18
// Use a Hashmap for the Entry API in order to prevent hashing twice.
15
19
// This can maybe be replaced with a HashSet once `get_or_insert_with`
16
20
// or a proper Entry API for Hashset is stable and meets this msrv
17
- used : HashMap < V , ( ) > ,
21
+ used : HashMap < V , ( ) , S > ,
18
22
f : F ,
19
23
}
20
24
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 >
22
26
where
23
27
I : Iterator + fmt:: Debug ,
24
28
V : fmt:: Debug + Hash + Eq ,
29
+ S : BuildHasher ,
25
30
{
26
31
debug_fmt_fields ! ( UniqueBy , iter, used) ;
27
32
}
28
33
29
34
/// 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 >
31
36
where
32
37
V : Eq + Hash ,
33
38
F : FnMut ( & I :: Item ) -> V ,
34
39
I : Iterator ,
40
+ S : BuildHasher ,
35
41
{
36
42
UniqueBy {
37
43
iter,
38
- used : HashMap :: new ( ) ,
44
+ used : HashMap :: with_hasher ( hash_builder ) ,
39
45
f,
40
46
}
41
47
}
42
48
43
49
// 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
45
51
where
46
52
I : IntoIterator < Item = K > ,
47
53
K : Hash + Eq ,
54
+ S : BuildHasher ,
48
55
{
49
56
let iter = iterable. into_iter ( ) ;
50
57
let current_used = used. len ( ) ;
51
58
used. extend ( iter. map ( |key| ( key, ( ) ) ) ) ;
52
59
used. len ( ) - current_used
53
60
}
54
61
55
- impl < I , V , F > Iterator for UniqueBy < I , V , F >
62
+ impl < I , V , F , S > Iterator for UniqueBy < I , V , F , S >
56
63
where
57
64
I : Iterator ,
58
65
V : Eq + Hash ,
59
66
F : FnMut ( & I :: Item ) -> V ,
67
+ S : BuildHasher ,
60
68
{
61
69
type Item = I :: Item ;
62
70
@@ -77,30 +85,33 @@ where
77
85
}
78
86
}
79
87
80
- impl < I , V , F > DoubleEndedIterator for UniqueBy < I , V , F >
88
+ impl < I , V , F , S > DoubleEndedIterator for UniqueBy < I , V , F , S >
81
89
where
82
90
I : DoubleEndedIterator ,
83
91
V : Eq + Hash ,
84
92
F : FnMut ( & I :: Item ) -> V ,
93
+ S : BuildHasher ,
85
94
{
86
95
fn next_back ( & mut self ) -> Option < Self :: Item > {
87
96
let Self { iter, used, f } = self ;
88
97
iter. rfind ( |v| used. insert ( f ( v) , ( ) ) . is_none ( ) )
89
98
}
90
99
}
91
100
92
- impl < I , V , F > FusedIterator for UniqueBy < I , V , F >
101
+ impl < I , V , F , S > FusedIterator for UniqueBy < I , V , F , S >
93
102
where
94
103
I : FusedIterator ,
95
104
V : Eq + Hash ,
96
105
F : FnMut ( & I :: Item ) -> V ,
106
+ S : BuildHasher ,
97
107
{
98
108
}
99
109
100
- impl < I > Iterator for Unique < I >
110
+ impl < I , S > Iterator for Unique < I , S >
101
111
where
102
112
I : Iterator ,
103
113
I :: Item : Eq + Hash + Clone ,
114
+ S : BuildHasher ,
104
115
{
105
116
type Item = I :: Item ;
106
117
@@ -127,10 +138,11 @@ where
127
138
}
128
139
}
129
140
130
- impl < I > DoubleEndedIterator for Unique < I >
141
+ impl < I , S > DoubleEndedIterator for Unique < I , S >
131
142
where
132
143
I : DoubleEndedIterator ,
133
144
I :: Item : Eq + Hash + Clone ,
145
+ S : BuildHasher ,
134
146
{
135
147
fn next_back ( & mut self ) -> Option < Self :: Item > {
136
148
let UniqueBy { iter, used, .. } = & mut self . iter ;
@@ -145,10 +157,11 @@ where
145
157
}
146
158
}
147
159
148
- impl < I > FusedIterator for Unique < I >
160
+ impl < I , S > FusedIterator for Unique < I , S >
149
161
where
150
162
I : FusedIterator ,
151
163
I :: Item : Eq + Hash + Clone ,
164
+ S : BuildHasher ,
152
165
{
153
166
}
154
167
@@ -157,31 +170,34 @@ where
157
170
/// See [`.unique()`](crate::Itertools::unique) for more information.
158
171
#[ derive( Clone ) ]
159
172
#[ must_use = "iterator adaptors are lazy and do nothing unless consumed" ]
160
- pub struct Unique < I >
173
+ pub struct Unique < I , S = RandomState >
161
174
where
162
175
I : Iterator ,
163
176
I :: Item : Eq + Hash + Clone ,
177
+ S : BuildHasher ,
164
178
{
165
- iter : UniqueBy < I , I :: Item , ( ) > ,
179
+ iter : UniqueBy < I , I :: Item , ( ) , S > ,
166
180
}
167
181
168
- impl < I > fmt:: Debug for Unique < I >
182
+ impl < I , S > fmt:: Debug for Unique < I , S >
169
183
where
170
184
I : Iterator + fmt:: Debug ,
171
185
I :: Item : Hash + Eq + fmt:: Debug + Clone ,
186
+ S : BuildHasher ,
172
187
{
173
188
debug_fmt_fields ! ( Unique , iter) ;
174
189
}
175
190
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 >
177
192
where
178
193
I : Iterator ,
179
194
I :: Item : Eq + Hash + Clone ,
195
+ S : BuildHasher ,
180
196
{
181
197
Unique {
182
198
iter : UniqueBy {
183
199
iter,
184
- used : HashMap :: new ( ) ,
200
+ used : HashMap :: with_hasher ( hash_builder ) ,
185
201
f : ( ) ,
186
202
} ,
187
203
}
0 commit comments