/rust/registry/src/index.crates.io-1949cf8c6b5b557f/itertools-0.14.0/src/merge_join.rs
Line | Count | Source |
1 | | use std::cmp::Ordering; |
2 | | use std::fmt; |
3 | | use std::iter::{Fuse, FusedIterator}; |
4 | | use std::marker::PhantomData; |
5 | | |
6 | | use either::Either; |
7 | | |
8 | | use super::adaptors::{put_back, PutBack}; |
9 | | use crate::either_or_both::EitherOrBoth; |
10 | | use crate::size_hint::{self, SizeHint}; |
11 | | #[cfg(doc)] |
12 | | use crate::Itertools; |
13 | | |
14 | | #[derive(Clone, Debug)] |
15 | | pub struct MergeLte; |
16 | | |
17 | | /// An iterator adaptor that merges the two base iterators in ascending order. |
18 | | /// If both base iterators are sorted (ascending), the result is sorted. |
19 | | /// |
20 | | /// Iterator element type is `I::Item`. |
21 | | /// |
22 | | /// See [`.merge()`](crate::Itertools::merge_by) for more information. |
23 | | pub type Merge<I, J> = MergeBy<I, J, MergeLte>; |
24 | | |
25 | | /// Create an iterator that merges elements in `i` and `j`. |
26 | | /// |
27 | | /// [`IntoIterator`] enabled version of [`Itertools::merge`](crate::Itertools::merge). |
28 | | /// |
29 | | /// ``` |
30 | | /// use itertools::merge; |
31 | | /// |
32 | | /// for elt in merge(&[1, 2, 3], &[2, 3, 4]) { |
33 | | /// /* loop body */ |
34 | | /// # let _ = elt; |
35 | | /// } |
36 | | /// ``` |
37 | 0 | pub fn merge<I, J>( |
38 | 0 | i: I, |
39 | 0 | j: J, |
40 | 0 | ) -> Merge<<I as IntoIterator>::IntoIter, <J as IntoIterator>::IntoIter> |
41 | 0 | where |
42 | 0 | I: IntoIterator, |
43 | 0 | J: IntoIterator<Item = I::Item>, |
44 | 0 | I::Item: PartialOrd, |
45 | | { |
46 | 0 | merge_by_new(i, j, MergeLte) |
47 | 0 | } |
48 | | |
49 | | /// An iterator adaptor that merges the two base iterators in ascending order. |
50 | | /// If both base iterators are sorted (ascending), the result is sorted. |
51 | | /// |
52 | | /// Iterator element type is `I::Item`. |
53 | | /// |
54 | | /// See [`.merge_by()`](crate::Itertools::merge_by) for more information. |
55 | | #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] |
56 | | pub struct MergeBy<I: Iterator, J: Iterator, F> { |
57 | | left: PutBack<Fuse<I>>, |
58 | | right: PutBack<Fuse<J>>, |
59 | | cmp_fn: F, |
60 | | } |
61 | | |
62 | | /// Create a `MergeBy` iterator. |
63 | 0 | pub fn merge_by_new<I, J, F>(a: I, b: J, cmp: F) -> MergeBy<I::IntoIter, J::IntoIter, F> |
64 | 0 | where |
65 | 0 | I: IntoIterator, |
66 | 0 | J: IntoIterator<Item = I::Item>, |
67 | | { |
68 | 0 | MergeBy { |
69 | 0 | left: put_back(a.into_iter().fuse()), |
70 | 0 | right: put_back(b.into_iter().fuse()), |
71 | 0 | cmp_fn: cmp, |
72 | 0 | } |
73 | 0 | } |
74 | | |
75 | | /// Return an iterator adaptor that merge-joins items from the two base iterators in ascending order. |
76 | | /// |
77 | | /// [`IntoIterator`] enabled version of [`Itertools::merge_join_by`]. |
78 | 0 | pub fn merge_join_by<I, J, F, T>( |
79 | 0 | left: I, |
80 | 0 | right: J, |
81 | 0 | cmp_fn: F, |
82 | 0 | ) -> MergeJoinBy<I::IntoIter, J::IntoIter, F> |
83 | 0 | where |
84 | 0 | I: IntoIterator, |
85 | 0 | J: IntoIterator, |
86 | 0 | F: FnMut(&I::Item, &J::Item) -> T, |
87 | | { |
88 | 0 | MergeBy { |
89 | 0 | left: put_back(left.into_iter().fuse()), |
90 | 0 | right: put_back(right.into_iter().fuse()), |
91 | 0 | cmp_fn: MergeFuncLR(cmp_fn, PhantomData), |
92 | 0 | } |
93 | 0 | } |
94 | | |
95 | | /// An iterator adaptor that merge-joins items from the two base iterators in ascending order. |
96 | | /// |
97 | | /// See [`.merge_join_by()`](crate::Itertools::merge_join_by) for more information. |
98 | | pub type MergeJoinBy<I, J, F> = |
99 | | MergeBy<I, J, MergeFuncLR<F, <F as FuncLR<<I as Iterator>::Item, <J as Iterator>::Item>>::T>>; |
100 | | |
101 | | #[derive(Clone, Debug)] |
102 | | pub struct MergeFuncLR<F, T>(F, PhantomData<T>); |
103 | | |
104 | | pub trait FuncLR<L, R> { |
105 | | type T; |
106 | | } |
107 | | |
108 | | impl<L, R, T, F: FnMut(&L, &R) -> T> FuncLR<L, R> for F { |
109 | | type T = T; |
110 | | } |
111 | | |
112 | | pub trait OrderingOrBool<L, R> { |
113 | | type MergeResult; |
114 | | fn left(left: L) -> Self::MergeResult; |
115 | | fn right(right: R) -> Self::MergeResult; |
116 | | // "merge" never returns (Some(...), Some(...), ...) so Option<Either<I::Item, J::Item>> |
117 | | // is appealing but it is always followed by two put_backs, so we think the compiler is |
118 | | // smart enough to optimize it. Or we could move put_backs into "merge". |
119 | | fn merge(&mut self, left: L, right: R) -> (Option<Either<L, R>>, Self::MergeResult); |
120 | | fn size_hint(left: SizeHint, right: SizeHint) -> SizeHint; |
121 | | } |
122 | | |
123 | | impl<L, R, F: FnMut(&L, &R) -> Ordering> OrderingOrBool<L, R> for MergeFuncLR<F, Ordering> { |
124 | | type MergeResult = EitherOrBoth<L, R>; |
125 | 0 | fn left(left: L) -> Self::MergeResult { |
126 | 0 | EitherOrBoth::Left(left) |
127 | 0 | } |
128 | 0 | fn right(right: R) -> Self::MergeResult { |
129 | 0 | EitherOrBoth::Right(right) |
130 | 0 | } |
131 | 0 | fn merge(&mut self, left: L, right: R) -> (Option<Either<L, R>>, Self::MergeResult) { |
132 | 0 | match self.0(&left, &right) { |
133 | 0 | Ordering::Equal => (None, EitherOrBoth::Both(left, right)), |
134 | 0 | Ordering::Less => (Some(Either::Right(right)), EitherOrBoth::Left(left)), |
135 | 0 | Ordering::Greater => (Some(Either::Left(left)), EitherOrBoth::Right(right)), |
136 | | } |
137 | 0 | } |
138 | 0 | fn size_hint(left: SizeHint, right: SizeHint) -> SizeHint { |
139 | 0 | let (a_lower, a_upper) = left; |
140 | 0 | let (b_lower, b_upper) = right; |
141 | 0 | let lower = ::std::cmp::max(a_lower, b_lower); |
142 | 0 | let upper = match (a_upper, b_upper) { |
143 | 0 | (Some(x), Some(y)) => x.checked_add(y), |
144 | 0 | _ => None, |
145 | | }; |
146 | 0 | (lower, upper) |
147 | 0 | } |
148 | | } |
149 | | |
150 | | impl<L, R, F: FnMut(&L, &R) -> bool> OrderingOrBool<L, R> for MergeFuncLR<F, bool> { |
151 | | type MergeResult = Either<L, R>; |
152 | 0 | fn left(left: L) -> Self::MergeResult { |
153 | 0 | Either::Left(left) |
154 | 0 | } |
155 | 0 | fn right(right: R) -> Self::MergeResult { |
156 | 0 | Either::Right(right) |
157 | 0 | } |
158 | 0 | fn merge(&mut self, left: L, right: R) -> (Option<Either<L, R>>, Self::MergeResult) { |
159 | 0 | if self.0(&left, &right) { |
160 | 0 | (Some(Either::Right(right)), Either::Left(left)) |
161 | | } else { |
162 | 0 | (Some(Either::Left(left)), Either::Right(right)) |
163 | | } |
164 | 0 | } |
165 | 0 | fn size_hint(left: SizeHint, right: SizeHint) -> SizeHint { |
166 | | // Not ExactSizeIterator because size may be larger than usize |
167 | 0 | size_hint::add(left, right) |
168 | 0 | } |
169 | | } |
170 | | |
171 | | impl<T, F: FnMut(&T, &T) -> bool> OrderingOrBool<T, T> for F { |
172 | | type MergeResult = T; |
173 | 0 | fn left(left: T) -> Self::MergeResult { |
174 | 0 | left |
175 | 0 | } |
176 | 0 | fn right(right: T) -> Self::MergeResult { |
177 | 0 | right |
178 | 0 | } |
179 | 0 | fn merge(&mut self, left: T, right: T) -> (Option<Either<T, T>>, Self::MergeResult) { |
180 | 0 | if self(&left, &right) { |
181 | 0 | (Some(Either::Right(right)), left) |
182 | | } else { |
183 | 0 | (Some(Either::Left(left)), right) |
184 | | } |
185 | 0 | } |
186 | 0 | fn size_hint(left: SizeHint, right: SizeHint) -> SizeHint { |
187 | | // Not ExactSizeIterator because size may be larger than usize |
188 | 0 | size_hint::add(left, right) |
189 | 0 | } |
190 | | } |
191 | | |
192 | | impl<T: PartialOrd> OrderingOrBool<T, T> for MergeLte { |
193 | | type MergeResult = T; |
194 | 0 | fn left(left: T) -> Self::MergeResult { |
195 | 0 | left |
196 | 0 | } |
197 | 0 | fn right(right: T) -> Self::MergeResult { |
198 | 0 | right |
199 | 0 | } |
200 | 0 | fn merge(&mut self, left: T, right: T) -> (Option<Either<T, T>>, Self::MergeResult) { |
201 | 0 | if left <= right { |
202 | 0 | (Some(Either::Right(right)), left) |
203 | | } else { |
204 | 0 | (Some(Either::Left(left)), right) |
205 | | } |
206 | 0 | } |
207 | 0 | fn size_hint(left: SizeHint, right: SizeHint) -> SizeHint { |
208 | | // Not ExactSizeIterator because size may be larger than usize |
209 | 0 | size_hint::add(left, right) |
210 | 0 | } |
211 | | } |
212 | | |
213 | | impl<I, J, F> Clone for MergeBy<I, J, F> |
214 | | where |
215 | | I: Iterator, |
216 | | J: Iterator, |
217 | | PutBack<Fuse<I>>: Clone, |
218 | | PutBack<Fuse<J>>: Clone, |
219 | | F: Clone, |
220 | | { |
221 | | clone_fields!(left, right, cmp_fn); |
222 | | } |
223 | | |
224 | | impl<I, J, F> fmt::Debug for MergeBy<I, J, F> |
225 | | where |
226 | | I: Iterator + fmt::Debug, |
227 | | I::Item: fmt::Debug, |
228 | | J: Iterator + fmt::Debug, |
229 | | J::Item: fmt::Debug, |
230 | | { |
231 | | debug_fmt_fields!(MergeBy, left, right); |
232 | | } |
233 | | |
234 | | impl<I, J, F> Iterator for MergeBy<I, J, F> |
235 | | where |
236 | | I: Iterator, |
237 | | J: Iterator, |
238 | | F: OrderingOrBool<I::Item, J::Item>, |
239 | | { |
240 | | type Item = F::MergeResult; |
241 | | |
242 | 0 | fn next(&mut self) -> Option<Self::Item> { |
243 | 0 | match (self.left.next(), self.right.next()) { |
244 | 0 | (None, None) => None, |
245 | 0 | (Some(left), None) => Some(F::left(left)), |
246 | 0 | (None, Some(right)) => Some(F::right(right)), |
247 | 0 | (Some(left), Some(right)) => { |
248 | 0 | let (not_next, next) = self.cmp_fn.merge(left, right); |
249 | 0 | match not_next { |
250 | 0 | Some(Either::Left(l)) => { |
251 | 0 | self.left.put_back(l); |
252 | 0 | } |
253 | 0 | Some(Either::Right(r)) => { |
254 | 0 | self.right.put_back(r); |
255 | 0 | } |
256 | 0 | None => (), |
257 | | } |
258 | | |
259 | 0 | Some(next) |
260 | | } |
261 | | } |
262 | 0 | } |
263 | | |
264 | 0 | fn fold<B, G>(mut self, init: B, mut f: G) -> B |
265 | 0 | where |
266 | 0 | Self: Sized, |
267 | 0 | G: FnMut(B, Self::Item) -> B, |
268 | | { |
269 | 0 | let mut acc = init; |
270 | 0 | let mut left = self.left.next(); |
271 | 0 | let mut right = self.right.next(); |
272 | | |
273 | | loop { |
274 | 0 | match (left, right) { |
275 | 0 | (Some(l), Some(r)) => match self.cmp_fn.merge(l, r) { |
276 | 0 | (Some(Either::Right(r)), x) => { |
277 | 0 | acc = f(acc, x); |
278 | 0 | left = self.left.next(); |
279 | 0 | right = Some(r); |
280 | 0 | } |
281 | 0 | (Some(Either::Left(l)), x) => { |
282 | 0 | acc = f(acc, x); |
283 | 0 | left = Some(l); |
284 | 0 | right = self.right.next(); |
285 | 0 | } |
286 | 0 | (None, x) => { |
287 | 0 | acc = f(acc, x); |
288 | 0 | left = self.left.next(); |
289 | 0 | right = self.right.next(); |
290 | 0 | } |
291 | | }, |
292 | 0 | (Some(l), None) => { |
293 | 0 | self.left.put_back(l); |
294 | 0 | acc = self.left.fold(acc, |acc, x| f(acc, F::left(x))); |
295 | 0 | break; |
296 | | } |
297 | 0 | (None, Some(r)) => { |
298 | 0 | self.right.put_back(r); |
299 | 0 | acc = self.right.fold(acc, |acc, x| f(acc, F::right(x))); |
300 | 0 | break; |
301 | | } |
302 | | (None, None) => { |
303 | 0 | break; |
304 | | } |
305 | | } |
306 | | } |
307 | | |
308 | 0 | acc |
309 | 0 | } |
310 | | |
311 | 0 | fn size_hint(&self) -> SizeHint { |
312 | 0 | F::size_hint(self.left.size_hint(), self.right.size_hint()) |
313 | 0 | } |
314 | | |
315 | 0 | fn nth(&mut self, mut n: usize) -> Option<Self::Item> { |
316 | | loop { |
317 | 0 | if n == 0 { |
318 | 0 | break self.next(); |
319 | 0 | } |
320 | 0 | n -= 1; |
321 | 0 | match (self.left.next(), self.right.next()) { |
322 | 0 | (None, None) => break None, |
323 | 0 | (Some(_left), None) => break self.left.nth(n).map(F::left), |
324 | 0 | (None, Some(_right)) => break self.right.nth(n).map(F::right), |
325 | 0 | (Some(left), Some(right)) => { |
326 | 0 | let (not_next, _) = self.cmp_fn.merge(left, right); |
327 | 0 | match not_next { |
328 | 0 | Some(Either::Left(l)) => { |
329 | 0 | self.left.put_back(l); |
330 | 0 | } |
331 | 0 | Some(Either::Right(r)) => { |
332 | 0 | self.right.put_back(r); |
333 | 0 | } |
334 | 0 | None => (), |
335 | | } |
336 | | } |
337 | | } |
338 | | } |
339 | 0 | } |
340 | | } |
341 | | |
342 | | impl<I, J, F> FusedIterator for MergeBy<I, J, F> |
343 | | where |
344 | | I: Iterator, |
345 | | J: Iterator, |
346 | | F: OrderingOrBool<I::Item, J::Item>, |
347 | | { |
348 | | } |