/rust/registry/src/index.crates.io-1949cf8c6b5b557f/itertools-0.10.5/src/unique_impl.rs
Line | Count | Source |
1 | | use std::collections::HashMap; |
2 | | use std::collections::hash_map::Entry; |
3 | | use std::hash::Hash; |
4 | | use std::fmt; |
5 | | use std::iter::FusedIterator; |
6 | | |
7 | | /// An iterator adapter to filter out duplicate elements. |
8 | | /// |
9 | | /// See [`.unique_by()`](crate::Itertools::unique) for more information. |
10 | | #[derive(Clone)] |
11 | | #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] |
12 | | pub struct UniqueBy<I: Iterator, V, F> { |
13 | | iter: I, |
14 | | // Use a Hashmap for the Entry API in order to prevent hashing twice. |
15 | | // This can maybe be replaced with a HashSet once `get_or_insert_with` |
16 | | // or a proper Entry API for Hashset is stable and meets this msrv |
17 | | used: HashMap<V, ()>, |
18 | | f: F, |
19 | | } |
20 | | |
21 | | impl<I, V, F> fmt::Debug for UniqueBy<I, V, F> |
22 | | where I: Iterator + fmt::Debug, |
23 | | V: fmt::Debug + Hash + Eq, |
24 | | { |
25 | | debug_fmt_fields!(UniqueBy, iter, used); |
26 | | } |
27 | | |
28 | | /// Create a new `UniqueBy` iterator. |
29 | 0 | pub fn unique_by<I, V, F>(iter: I, f: F) -> UniqueBy<I, V, F> |
30 | 0 | where V: Eq + Hash, |
31 | 0 | F: FnMut(&I::Item) -> V, |
32 | 0 | I: Iterator, |
33 | | { |
34 | 0 | UniqueBy { |
35 | 0 | iter, |
36 | 0 | used: HashMap::new(), |
37 | 0 | f, |
38 | 0 | } |
39 | 0 | } |
40 | | |
41 | | // count the number of new unique keys in iterable (`used` is the set already seen) |
42 | 0 | fn count_new_keys<I, K>(mut used: HashMap<K, ()>, iterable: I) -> usize |
43 | 0 | where I: IntoIterator<Item=K>, |
44 | 0 | K: Hash + Eq, |
45 | | { |
46 | 0 | let iter = iterable.into_iter(); |
47 | 0 | let current_used = used.len(); |
48 | 0 | used.extend(iter.map(|key| (key, ()))); |
49 | 0 | used.len() - current_used |
50 | 0 | } |
51 | | |
52 | | impl<I, V, F> Iterator for UniqueBy<I, V, F> |
53 | | where I: Iterator, |
54 | | V: Eq + Hash, |
55 | | F: FnMut(&I::Item) -> V |
56 | | { |
57 | | type Item = I::Item; |
58 | | |
59 | 0 | fn next(&mut self) -> Option<Self::Item> { |
60 | 0 | while let Some(v) = self.iter.next() { |
61 | 0 | let key = (self.f)(&v); |
62 | 0 | if self.used.insert(key, ()).is_none() { |
63 | 0 | return Some(v); |
64 | 0 | } |
65 | | } |
66 | 0 | None |
67 | 0 | } |
68 | | |
69 | | #[inline] |
70 | 0 | fn size_hint(&self) -> (usize, Option<usize>) { |
71 | 0 | let (low, hi) = self.iter.size_hint(); |
72 | 0 | ((low > 0 && self.used.is_empty()) as usize, hi) |
73 | 0 | } |
74 | | |
75 | 0 | fn count(self) -> usize { |
76 | 0 | let mut key_f = self.f; |
77 | 0 | count_new_keys(self.used, self.iter.map(move |elt| key_f(&elt))) |
78 | 0 | } |
79 | | } |
80 | | |
81 | | impl<I, V, F> DoubleEndedIterator for UniqueBy<I, V, F> |
82 | | where I: DoubleEndedIterator, |
83 | | V: Eq + Hash, |
84 | | F: FnMut(&I::Item) -> V |
85 | | { |
86 | 0 | fn next_back(&mut self) -> Option<Self::Item> { |
87 | 0 | while let Some(v) = self.iter.next_back() { |
88 | 0 | let key = (self.f)(&v); |
89 | 0 | if self.used.insert(key, ()).is_none() { |
90 | 0 | return Some(v); |
91 | 0 | } |
92 | | } |
93 | 0 | None |
94 | 0 | } |
95 | | } |
96 | | |
97 | | impl<I, V, F> FusedIterator for UniqueBy<I, V, F> |
98 | | where I: FusedIterator, |
99 | | V: Eq + Hash, |
100 | | F: FnMut(&I::Item) -> V |
101 | | {} |
102 | | |
103 | | impl<I> Iterator for Unique<I> |
104 | | where I: Iterator, |
105 | | I::Item: Eq + Hash + Clone |
106 | | { |
107 | | type Item = I::Item; |
108 | | |
109 | 0 | fn next(&mut self) -> Option<Self::Item> { |
110 | 0 | while let Some(v) = self.iter.iter.next() { |
111 | 0 | if let Entry::Vacant(entry) = self.iter.used.entry(v) { |
112 | 0 | let elt = entry.key().clone(); |
113 | 0 | entry.insert(()); |
114 | 0 | return Some(elt); |
115 | 0 | } |
116 | | } |
117 | 0 | None |
118 | 0 | } |
119 | | |
120 | | #[inline] |
121 | 0 | fn size_hint(&self) -> (usize, Option<usize>) { |
122 | 0 | let (low, hi) = self.iter.iter.size_hint(); |
123 | 0 | ((low > 0 && self.iter.used.is_empty()) as usize, hi) |
124 | 0 | } |
125 | | |
126 | 0 | fn count(self) -> usize { |
127 | 0 | count_new_keys(self.iter.used, self.iter.iter) |
128 | 0 | } |
129 | | } |
130 | | |
131 | | impl<I> DoubleEndedIterator for Unique<I> |
132 | | where I: DoubleEndedIterator, |
133 | | I::Item: Eq + Hash + Clone |
134 | | { |
135 | 0 | fn next_back(&mut self) -> Option<Self::Item> { |
136 | 0 | while let Some(v) = self.iter.iter.next_back() { |
137 | 0 | if let Entry::Vacant(entry) = self.iter.used.entry(v) { |
138 | 0 | let elt = entry.key().clone(); |
139 | 0 | entry.insert(()); |
140 | 0 | return Some(elt); |
141 | 0 | } |
142 | | } |
143 | 0 | None |
144 | 0 | } |
145 | | } |
146 | | |
147 | | impl<I> FusedIterator for Unique<I> |
148 | | where I: FusedIterator, |
149 | | I::Item: Eq + Hash + Clone |
150 | | {} |
151 | | |
152 | | /// An iterator adapter to filter out duplicate elements. |
153 | | /// |
154 | | /// See [`.unique()`](crate::Itertools::unique) for more information. |
155 | | #[derive(Clone)] |
156 | | #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] |
157 | | pub struct Unique<I: Iterator> { |
158 | | iter: UniqueBy<I, I::Item, ()>, |
159 | | } |
160 | | |
161 | | impl<I> fmt::Debug for Unique<I> |
162 | | where I: Iterator + fmt::Debug, |
163 | | I::Item: Hash + Eq + fmt::Debug, |
164 | | { |
165 | | debug_fmt_fields!(Unique, iter); |
166 | | } |
167 | | |
168 | 0 | pub fn unique<I>(iter: I) -> Unique<I> |
169 | 0 | where I: Iterator, |
170 | 0 | I::Item: Eq + Hash, |
171 | | { |
172 | 0 | Unique { |
173 | 0 | iter: UniqueBy { |
174 | 0 | iter, |
175 | 0 | used: HashMap::new(), |
176 | 0 | f: (), |
177 | 0 | } |
178 | 0 | } |
179 | 0 | } |