Skip to content

Commit f920a9c

Browse files
Philippe-Choletphimuemue
authored andcommitted
Move Merge/MergeBy from "adaptors" to "merge_join"
1 parent cb46a5f commit f920a9c

File tree

4 files changed

+142
-143
lines changed

4 files changed

+142
-143
lines changed

src/adaptors/mod.rs

Lines changed: 1 addition & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pub use self::map::MapResults;
1515
pub use self::multi_product::*;
1616

1717
use std::fmt;
18-
use std::iter::{Fuse, Peekable, FromIterator, FusedIterator};
18+
use std::iter::{Fuse, FromIterator, FusedIterator};
1919
use std::marker::PhantomData;
2020
use crate::size_hint;
2121

@@ -466,142 +466,6 @@ impl<I> ExactSizeIterator for Step<I>
466466
where I: ExactSizeIterator
467467
{}
468468

469-
pub trait MergePredicate<T> {
470-
fn merge_pred(&mut self, a: &T, b: &T) -> bool;
471-
}
472-
473-
#[derive(Clone, Debug)]
474-
pub struct MergeLte;
475-
476-
impl<T: PartialOrd> MergePredicate<T> for MergeLte {
477-
fn merge_pred(&mut self, a: &T, b: &T) -> bool {
478-
a <= b
479-
}
480-
}
481-
482-
/// An iterator adaptor that merges the two base iterators in ascending order.
483-
/// If both base iterators are sorted (ascending), the result is sorted.
484-
///
485-
/// Iterator element type is `I::Item`.
486-
///
487-
/// See [`.merge()`](crate::Itertools::merge_by) for more information.
488-
pub type Merge<I, J> = MergeBy<I, J, MergeLte>;
489-
490-
/// Create an iterator that merges elements in `i` and `j`.
491-
///
492-
/// [`IntoIterator`] enabled version of [`Itertools::merge`](crate::Itertools::merge).
493-
///
494-
/// ```
495-
/// use itertools::merge;
496-
///
497-
/// for elt in merge(&[1, 2, 3], &[2, 3, 4]) {
498-
/// /* loop body */
499-
/// }
500-
/// ```
501-
pub fn merge<I, J>(i: I, j: J) -> Merge<<I as IntoIterator>::IntoIter, <J as IntoIterator>::IntoIter>
502-
where I: IntoIterator,
503-
J: IntoIterator<Item = I::Item>,
504-
I::Item: PartialOrd
505-
{
506-
merge_by_new(i, j, MergeLte)
507-
}
508-
509-
/// An iterator adaptor that merges the two base iterators in ascending order.
510-
/// If both base iterators are sorted (ascending), the result is sorted.
511-
///
512-
/// Iterator element type is `I::Item`.
513-
///
514-
/// See [`.merge_by()`](crate::Itertools::merge_by) for more information.
515-
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
516-
pub struct MergeBy<I, J, F>
517-
where I: Iterator,
518-
J: Iterator<Item = I::Item>
519-
{
520-
a: Peekable<I>,
521-
b: Peekable<J>,
522-
fused: Option<bool>,
523-
cmp: F,
524-
}
525-
526-
impl<I, J, F> fmt::Debug for MergeBy<I, J, F>
527-
where I: Iterator + fmt::Debug, J: Iterator<Item = I::Item> + fmt::Debug,
528-
I::Item: fmt::Debug,
529-
{
530-
debug_fmt_fields!(MergeBy, a, b);
531-
}
532-
533-
impl<T, F: FnMut(&T, &T)->bool> MergePredicate<T> for F {
534-
fn merge_pred(&mut self, a: &T, b: &T) -> bool {
535-
self(a, b)
536-
}
537-
}
538-
539-
/// Create a `MergeBy` iterator.
540-
pub fn merge_by_new<I, J, F>(a: I, b: J, cmp: F) -> MergeBy<I::IntoIter, J::IntoIter, F>
541-
where I: IntoIterator,
542-
J: IntoIterator<Item = I::Item>,
543-
F: MergePredicate<I::Item>,
544-
{
545-
MergeBy {
546-
a: a.into_iter().peekable(),
547-
b: b.into_iter().peekable(),
548-
fused: None,
549-
cmp,
550-
}
551-
}
552-
553-
impl<I, J, F> Clone for MergeBy<I, J, F>
554-
where I: Iterator,
555-
J: Iterator<Item = I::Item>,
556-
Peekable<I>: Clone,
557-
Peekable<J>: Clone,
558-
F: Clone
559-
{
560-
clone_fields!(a, b, fused, cmp);
561-
}
562-
563-
impl<I, J, F> Iterator for MergeBy<I, J, F>
564-
where I: Iterator,
565-
J: Iterator<Item = I::Item>,
566-
F: MergePredicate<I::Item>
567-
{
568-
type Item = I::Item;
569-
570-
fn next(&mut self) -> Option<Self::Item> {
571-
let less_than = match self.fused {
572-
Some(lt) => lt,
573-
None => match (self.a.peek(), self.b.peek()) {
574-
(Some(a), Some(b)) => self.cmp.merge_pred(a, b),
575-
(Some(_), None) => {
576-
self.fused = Some(true);
577-
true
578-
}
579-
(None, Some(_)) => {
580-
self.fused = Some(false);
581-
false
582-
}
583-
(None, None) => return None,
584-
}
585-
};
586-
if less_than {
587-
self.a.next()
588-
} else {
589-
self.b.next()
590-
}
591-
}
592-
593-
fn size_hint(&self) -> (usize, Option<usize>) {
594-
// Not ExactSizeIterator because size may be larger than usize
595-
size_hint::add(self.a.size_hint(), self.b.size_hint())
596-
}
597-
}
598-
599-
impl<I, J, F> FusedIterator for MergeBy<I, J, F>
600-
where I: FusedIterator,
601-
J: FusedIterator<Item = I::Item>,
602-
F: MergePredicate<I::Item>
603-
{}
604-
605469
/// An iterator adaptor that borrows from a `Clone`-able iterator
606470
/// to only pick off elements while the predicate returns `true`.
607471
///

src/free.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ use crate::intersperse::{Intersperse, IntersperseWith};
1919

2020
pub use crate::adaptors::{
2121
interleave,
22-
merge,
2322
put_back,
2423
};
2524
#[cfg(feature = "use_alloc")]
@@ -31,7 +30,7 @@ pub use crate::peek_nth::peek_nth;
3130
#[cfg(feature = "use_alloc")]
3231
pub use crate::kmerge_impl::kmerge;
3332
pub use crate::zip_eq_impl::zip_eq;
34-
pub use crate::merge_join::merge_join_by;
33+
pub use crate::merge_join::{merge, merge_join_by};
3534
#[cfg(feature = "use_alloc")]
3635
pub use crate::rciter_impl::rciter;
3736

src/lib.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,6 @@ pub mod structs {
9999
Batching,
100100
MapInto,
101101
MapOk,
102-
Merge,
103-
MergeBy,
104102
TakeWhileRef,
105103
WhileSome,
106104
Coalesce,
@@ -127,7 +125,7 @@ pub mod structs {
127125
pub use crate::intersperse::{Intersperse, IntersperseWith};
128126
#[cfg(feature = "use_alloc")]
129127
pub use crate::kmerge_impl::{KMerge, KMergeBy};
130-
pub use crate::merge_join::MergeJoinBy;
128+
pub use crate::merge_join::{Merge, MergeBy, MergeJoinBy};
131129
#[cfg(feature = "use_alloc")]
132130
pub use crate::multipeek_impl::MultiPeek;
133131
#[cfg(feature = "use_alloc")]
@@ -1008,7 +1006,7 @@ pub trait Itertools : Iterator {
10081006
J: IntoIterator<Item = Self::Item>,
10091007
F: FnMut(&Self::Item, &Self::Item) -> bool
10101008
{
1011-
adaptors::merge_by_new(self, other.into_iter(), is_first)
1009+
merge_join::merge_by_new(self, other.into_iter(), is_first)
10121010
}
10131011

10141012
/// Create an iterator that merges items from both this and the specified

src/merge_join.rs

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::cmp::Ordering;
22
use std::iter::Fuse;
3+
use std::iter::{Peekable, FusedIterator};
34
use std::fmt;
45

56
use either::Either;
@@ -10,6 +11,143 @@ use crate::size_hint::{self, SizeHint};
1011
#[cfg(doc)]
1112
use crate::Itertools;
1213

14+
pub trait MergePredicate<T> {
15+
fn merge_pred(&mut self, a: &T, b: &T) -> bool;
16+
}
17+
18+
#[derive(Clone, Debug)]
19+
pub struct MergeLte;
20+
21+
impl<T: PartialOrd> MergePredicate<T> for MergeLte {
22+
fn merge_pred(&mut self, a: &T, b: &T) -> bool {
23+
a <= b
24+
}
25+
}
26+
27+
/// An iterator adaptor that merges the two base iterators in ascending order.
28+
/// If both base iterators are sorted (ascending), the result is sorted.
29+
///
30+
/// Iterator element type is `I::Item`.
31+
///
32+
/// See [`.merge()`](crate::Itertools::merge_by) for more information.
33+
pub type Merge<I, J> = MergeBy<I, J, MergeLte>;
34+
35+
/// Create an iterator that merges elements in `i` and `j`.
36+
///
37+
/// [`IntoIterator`] enabled version of [`Itertools::merge`](crate::Itertools::merge).
38+
///
39+
/// ```
40+
/// use itertools::merge;
41+
///
42+
/// for elt in merge(&[1, 2, 3], &[2, 3, 4]) {
43+
/// /* loop body */
44+
/// }
45+
/// ```
46+
pub fn merge<I, J>(i: I, j: J) -> Merge<<I as IntoIterator>::IntoIter, <J as IntoIterator>::IntoIter>
47+
where I: IntoIterator,
48+
J: IntoIterator<Item = I::Item>,
49+
I::Item: PartialOrd
50+
{
51+
merge_by_new(i, j, MergeLte)
52+
}
53+
54+
/// An iterator adaptor that merges the two base iterators in ascending order.
55+
/// If both base iterators are sorted (ascending), the result is sorted.
56+
///
57+
/// Iterator element type is `I::Item`.
58+
///
59+
/// See [`.merge_by()`](crate::Itertools::merge_by) for more information.
60+
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
61+
pub struct MergeBy<I, J, F>
62+
where I: Iterator,
63+
J: Iterator<Item = I::Item>
64+
{
65+
a: Peekable<I>,
66+
b: Peekable<J>,
67+
fused: Option<bool>,
68+
cmp: F,
69+
}
70+
71+
impl<I, J, F> fmt::Debug for MergeBy<I, J, F>
72+
where I: Iterator + fmt::Debug, J: Iterator<Item = I::Item> + fmt::Debug,
73+
I::Item: fmt::Debug,
74+
{
75+
debug_fmt_fields!(MergeBy, a, b);
76+
}
77+
78+
impl<T, F: FnMut(&T, &T)->bool> MergePredicate<T> for F {
79+
fn merge_pred(&mut self, a: &T, b: &T) -> bool {
80+
self(a, b)
81+
}
82+
}
83+
84+
/// Create a `MergeBy` iterator.
85+
pub fn merge_by_new<I, J, F>(a: I, b: J, cmp: F) -> MergeBy<I::IntoIter, J::IntoIter, F>
86+
where I: IntoIterator,
87+
J: IntoIterator<Item = I::Item>,
88+
F: MergePredicate<I::Item>,
89+
{
90+
MergeBy {
91+
a: a.into_iter().peekable(),
92+
b: b.into_iter().peekable(),
93+
fused: None,
94+
cmp,
95+
}
96+
}
97+
98+
impl<I, J, F> Clone for MergeBy<I, J, F>
99+
where I: Iterator,
100+
J: Iterator<Item = I::Item>,
101+
Peekable<I>: Clone,
102+
Peekable<J>: Clone,
103+
F: Clone
104+
{
105+
clone_fields!(a, b, fused, cmp);
106+
}
107+
108+
impl<I, J, F> Iterator for MergeBy<I, J, F>
109+
where I: Iterator,
110+
J: Iterator<Item = I::Item>,
111+
F: MergePredicate<I::Item>
112+
{
113+
type Item = I::Item;
114+
115+
fn next(&mut self) -> Option<Self::Item> {
116+
let less_than = match self.fused {
117+
Some(lt) => lt,
118+
None => match (self.a.peek(), self.b.peek()) {
119+
(Some(a), Some(b)) => self.cmp.merge_pred(a, b),
120+
(Some(_), None) => {
121+
self.fused = Some(true);
122+
true
123+
}
124+
(None, Some(_)) => {
125+
self.fused = Some(false);
126+
false
127+
}
128+
(None, None) => return None,
129+
}
130+
};
131+
if less_than {
132+
self.a.next()
133+
} else {
134+
self.b.next()
135+
}
136+
}
137+
138+
fn size_hint(&self) -> (usize, Option<usize>) {
139+
// Not ExactSizeIterator because size may be larger than usize
140+
size_hint::add(self.a.size_hint(), self.b.size_hint())
141+
}
142+
}
143+
144+
impl<I, J, F> FusedIterator for MergeBy<I, J, F>
145+
where I: FusedIterator,
146+
J: FusedIterator<Item = I::Item>,
147+
F: MergePredicate<I::Item>
148+
{}
149+
150+
13151
/// Return an iterator adaptor that merge-joins items from the two base iterators in ascending order.
14152
///
15153
/// [`IntoIterator`] enabled version of [`Itertools::merge_join_by`].

0 commit comments

Comments
 (0)