From 8444c78c5c961ef60ffefce45dad58e7ca5c7a05 Mon Sep 17 00:00:00 2001 From: Philippe-Cholet Date: Thu, 24 Aug 2023 12:02:52 +0200 Subject: [PATCH] Make `MergeBy` an alias of `InternalMergeJoinBy` Being now an alias, we can remove various implementations. `FusedIterator` will be inserted back soon. We don't need `MergePredicate` anymore because we use two new implementations of `OrderingOrBool`. --- src/merge_join.rs | 142 ++++++++++++++++------------------------------ 1 file changed, 49 insertions(+), 93 deletions(-) diff --git a/src/merge_join.rs b/src/merge_join.rs index bbe87a480..3322ed18d 100644 --- a/src/merge_join.rs +++ b/src/merge_join.rs @@ -1,6 +1,5 @@ use std::cmp::Ordering; use std::iter::Fuse; -use std::iter::{Peekable, FusedIterator}; use std::fmt; use std::marker::PhantomData; @@ -12,19 +11,9 @@ use crate::size_hint::{self, SizeHint}; #[cfg(doc)] use crate::Itertools; -pub trait MergePredicate { - fn merge_pred(&mut self, a: &T, b: &T) -> bool; -} - #[derive(Clone, Debug)] pub struct MergeLte; -impl MergePredicate for MergeLte { - fn merge_pred(&mut self, a: &T, b: &T) -> bool { - a <= b - } -} - /// An iterator adaptor that merges the two base iterators in ascending order. /// If both base iterators are sorted (ascending), the result is sorted. /// @@ -58,97 +47,20 @@ pub fn merge(i: I, j: J) -> Merge<::IntoIter, - where I: Iterator, - J: Iterator -{ - a: Peekable, - b: Peekable, - fused: Option, - cmp: F, -} - -impl fmt::Debug for MergeBy - where I: Iterator + fmt::Debug, J: Iterator + fmt::Debug, - I::Item: fmt::Debug, -{ - debug_fmt_fields!(MergeBy, a, b); -} - -implbool> MergePredicate for F { - fn merge_pred(&mut self, a: &T, b: &T) -> bool { - self(a, b) - } -} +pub type MergeBy = InternalMergeJoinBy; /// Create a `MergeBy` iterator. pub fn merge_by_new(a: I, b: J, cmp: F) -> MergeBy where I: IntoIterator, J: IntoIterator, - F: MergePredicate, { - MergeBy { - a: a.into_iter().peekable(), - b: b.into_iter().peekable(), - fused: None, - cmp, - } -} - -impl Clone for MergeBy - where I: Iterator, - J: Iterator, - Peekable: Clone, - Peekable: Clone, - F: Clone -{ - clone_fields!(a, b, fused, cmp); -} - -impl Iterator for MergeBy - where I: Iterator, - J: Iterator, - F: MergePredicate -{ - type Item = I::Item; - - fn next(&mut self) -> Option { - let less_than = match self.fused { - Some(lt) => lt, - None => match (self.a.peek(), self.b.peek()) { - (Some(a), Some(b)) => self.cmp.merge_pred(a, b), - (Some(_), None) => { - self.fused = Some(true); - true - } - (None, Some(_)) => { - self.fused = Some(false); - false - } - (None, None) => return None, - } - }; - if less_than { - self.a.next() - } else { - self.b.next() - } - } - - fn size_hint(&self) -> (usize, Option) { - // Not ExactSizeIterator because size may be larger than usize - size_hint::add(self.a.size_hint(), self.b.size_hint()) + InternalMergeJoinBy { + left: put_back(a.into_iter().fuse()), + right: put_back(b.into_iter().fuse()), + cmp_fn: cmp, } } -impl FusedIterator for MergeBy - where I: FusedIterator, - J: FusedIterator, - F: MergePredicate -{} - - /// Return an iterator adaptor that merge-joins items from the two base iterators in ascending order. /// /// [`IntoIterator`] enabled version of [`Itertools::merge_join_by`]. @@ -250,6 +162,50 @@ impl bool> OrderingOrBool for MergeFuncLR bool> OrderingOrBool for F { + type Out = bool; + type MergeResult = T; + fn left(left: T) -> Self::MergeResult { + left + } + fn right(right: T) -> Self::MergeResult { + right + } + fn merge(&mut self, left: T, right: T) -> (Option, Option, Self::MergeResult) { + if self(&left, &right) { + (None, Some(right), left) + } else { + (Some(left), None, right) + } + } + fn size_hint(left: SizeHint, right: SizeHint) -> SizeHint { + // Not ExactSizeIterator because size may be larger than usize + size_hint::add(left, right) + } +} + +impl OrderingOrBool for MergeLte { + type Out = bool; + type MergeResult = T; + fn left(left: T) -> Self::MergeResult { + left + } + fn right(right: T) -> Self::MergeResult { + right + } + fn merge(&mut self, left: T, right: T) -> (Option, Option, Self::MergeResult) { + if left <= right { + (None, Some(right), left) + } else { + (Some(left), None, right) + } + } + fn size_hint(left: SizeHint, right: SizeHint) -> SizeHint { + // Not ExactSizeIterator because size may be larger than usize + size_hint::add(left, right) + } +} + impl Clone for InternalMergeJoinBy where I: Iterator, J: Iterator,