Skip to content

Commit 32b4d3e

Browse files
bors[bot]phimuemue
andauthored
Merge #364
364: Express KMerge in terms of KMergeBy r=jswrenn a=phimuemue This is a follow up to #360: * First, I brought `KMergeBy` in line with `KMerge` by `impl Clone` (if possible). * Then, I substitute `KMerge` by a specialized `KMergeBy`. * At last, I express `kmerge` in terms of `kmerge_by`. Co-authored-by: philipp <[email protected]>
2 parents 7cab90c + e3ab4bc commit 32b4d3e

File tree

1 file changed

+31
-56
lines changed

1 file changed

+31
-56
lines changed

src/kmerge_impl.rs

Lines changed: 31 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -112,17 +112,25 @@ fn sift_down<T, S>(heap: &mut [T], index: usize, mut less_than: S)
112112
///
113113
/// See [`.kmerge()`](../trait.Itertools.html#method.kmerge) for more information.
114114
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
115-
pub struct KMerge<I>
116-
where I: Iterator
117-
{
118-
heap: Vec<HeadTail<I>>,
115+
pub type KMerge<I> = KMergeBy<I, KMergeByLt>;
116+
117+
pub trait KMergePredicate<T> {
118+
fn kmerge_pred(&mut self, a: &T, b: &T) -> bool;
119119
}
120120

121-
impl<I> fmt::Debug for KMerge<I>
122-
where I: Iterator + fmt::Debug,
123-
I::Item: fmt::Debug,
124-
{
125-
debug_fmt_fields!(KMerge, heap);
121+
#[derive(Clone)]
122+
pub struct KMergeByLt;
123+
124+
impl<T: PartialOrd> KMergePredicate<T> for KMergeByLt {
125+
fn kmerge_pred(&mut self, a: &T, b: &T) -> bool {
126+
a < b
127+
}
128+
}
129+
130+
impl<T, F: FnMut(&T, &T)->bool> KMergePredicate<T> for F {
131+
fn kmerge_pred(&mut self, a: &T, b: &T) -> bool {
132+
self(a, b)
133+
}
126134
}
127135

128136
/// Create an iterator that merges elements of the contained iterators using
@@ -142,48 +150,7 @@ pub fn kmerge<I>(iterable: I) -> KMerge<<I::Item as IntoIterator>::IntoIter>
142150
I::Item: IntoIterator,
143151
<<I as IntoIterator>::Item as IntoIterator>::Item: PartialOrd
144152
{
145-
let iter = iterable.into_iter();
146-
let (lower, _) = iter.size_hint();
147-
let mut heap = Vec::with_capacity(lower);
148-
heap.extend(iter.filter_map(|it| HeadTail::new(it.into_iter())));
149-
heapify(&mut heap, |a, b| a.head < b.head);
150-
KMerge { heap: heap }
151-
}
152-
153-
impl<I> Clone for KMerge<I>
154-
where I: Iterator + Clone,
155-
I::Item: Clone
156-
{
157-
fn clone(&self) -> KMerge<I> {
158-
clone_fields!(KMerge, self, heap)
159-
}
160-
}
161-
162-
impl<I> Iterator for KMerge<I>
163-
where I: Iterator,
164-
I::Item: PartialOrd
165-
{
166-
type Item = I::Item;
167-
168-
fn next(&mut self) -> Option<Self::Item> {
169-
if self.heap.is_empty() {
170-
return None;
171-
}
172-
let result = if let Some(next) = self.heap[0].next() {
173-
next
174-
} else {
175-
self.heap.swap_remove(0).head
176-
};
177-
sift_down(&mut self.heap, 0, |a, b| a.head < b.head);
178-
Some(result)
179-
}
180-
181-
fn size_hint(&self) -> (usize, Option<usize>) {
182-
self.heap.iter()
183-
.map(|i| i.size_hint())
184-
.fold1(size_hint::add)
185-
.unwrap_or((0, Some(0)))
186-
}
153+
kmerge_by(iterable, KMergeByLt)
187154
}
188155

189156
/// An iterator adaptor that merges an abitrary number of base iterators
@@ -215,21 +182,29 @@ pub fn kmerge_by<I, F>(iterable: I, mut less_than: F)
215182
-> KMergeBy<<I::Item as IntoIterator>::IntoIter, F>
216183
where I: IntoIterator,
217184
I::Item: IntoIterator,
218-
F: FnMut(&<<I as IntoIterator>::Item as IntoIterator>::Item,
219-
&<<I as IntoIterator>::Item as IntoIterator>::Item) -> bool
185+
F: KMergePredicate<<<I as IntoIterator>::Item as IntoIterator>::Item>,
220186
{
221187
let iter = iterable.into_iter();
222188
let (lower, _) = iter.size_hint();
223189
let mut heap: Vec<_> = Vec::with_capacity(lower);
224190
heap.extend(iter.filter_map(|it| HeadTail::new(it.into_iter())));
225-
heapify(&mut heap, |a, b| less_than(&a.head, &b.head));
191+
heapify(&mut heap, |a, b| less_than.kmerge_pred(&a.head, &b.head));
226192
KMergeBy { heap: heap, less_than: less_than }
227193
}
228194

195+
impl<I, F> Clone for KMergeBy<I, F>
196+
where I: Iterator + Clone,
197+
I::Item: Clone,
198+
F: Clone,
199+
{
200+
fn clone(&self) -> KMergeBy<I, F> {
201+
clone_fields!(KMergeBy, self, heap, less_than)
202+
}
203+
}
229204

230205
impl<I, F> Iterator for KMergeBy<I, F>
231206
where I: Iterator,
232-
F: FnMut(&I::Item, &I::Item) -> bool
207+
F: KMergePredicate<I::Item>
233208
{
234209
type Item = I::Item;
235210

@@ -243,7 +218,7 @@ impl<I, F> Iterator for KMergeBy<I, F>
243218
self.heap.swap_remove(0).head
244219
};
245220
let less_than = &mut self.less_than;
246-
sift_down(&mut self.heap, 0, |a, b| less_than(&a.head, &b.head));
221+
sift_down(&mut self.heap, 0, |a, b| less_than.kmerge_pred(&a.head, &b.head));
247222
Some(result)
248223
}
249224

0 commit comments

Comments
 (0)