8 macro_rules
! clone_fields
{
9 ($name
:ident
, $base
:expr
, $
($field
:ident
),+) => (
12 $field
: $base
. $field
.clone()
18 /// Head element and Tail iterator pair
20 /// `PartialEq`, `Eq`, `PartialOrd` and `Ord` are implemented by comparing sequences based on
21 /// first items (which are guaranteed to exist).
23 /// The meanings of `PartialOrd` and `Ord` are reversed so as to turn the heap used in
24 /// `KMerge` into a min-heap.
36 /// Constructs a `HeadTail` from an `Iterator`. Returns `None` if the `Iterator` is empty.
37 fn new(mut it
: I
) -> Option
<HeadTail
<I
>> {
47 /// Get the next element and update `head`, returning the old head in `Some`.
49 /// Returns `None` when the tail is exhausted (only `head` then remains).
50 fn next(&mut self) -> Option
<I
::Item
> {
51 if let Some(next
) = self.tail
.next() {
52 Some(replace(&mut self.head
, next
))
58 /// Hints at the size of the sequence, same as the `Iterator` method.
59 fn size_hint(&self) -> (usize, Option
<usize>) {
60 size_hint
::add_scalar(self.tail
.size_hint(), 1)
64 impl<I
> Clone
for HeadTail
<I
>
65 where I
: Iterator
+ Clone
,
68 fn clone(&self) -> Self {
69 clone_fields
!(HeadTail
, self, head
, tail
)
73 /// Make `data` a heap (min-heap w.r.t the sorting).
74 fn heapify
<T
, S
>(data
: &mut [T
], mut less_than
: S
)
75 where S
: FnMut(&T
, &T
) -> bool
77 for i
in (0..data
.len() / 2).rev() {
78 sift_down(data
, i
, &mut less_than
);
82 /// Sift down element at `index` (`heap` is a min-heap wrt the ordering)
83 fn sift_down
<T
, S
>(heap
: &mut [T
], index
: usize, mut less_than
: S
)
84 where S
: FnMut(&T
, &T
) -> bool
86 debug_assert
!(index
<= heap
.len());
88 let mut child
= 2 * pos
+ 1;
89 // the `pos` conditional is to avoid a bounds check
90 while pos
< heap
.len() && child
< heap
.len() {
91 let right
= child
+ 1;
93 // pick the smaller of the two children
94 if right
< heap
.len() && less_than(&heap
[right
], &heap
[child
]) {
98 // sift down is done if we are already in order
99 if !less_than(&heap
[child
], &heap
[pos
]) {
102 heap
.swap(pos
, child
);
108 /// An iterator adaptor that merges an abitrary number of base iterators in ascending order.
109 /// If all base iterators are sorted (ascending), the result is sorted.
111 /// Iterator element type is `I::Item`.
113 /// See [`.kmerge()`](../trait.Itertools.html#method.kmerge) for more information.
114 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
118 heap
: Vec
<HeadTail
<I
>>,
121 impl<I
> fmt
::Debug
for KMerge
<I
>
122 where I
: Iterator
+ fmt
::Debug
,
125 debug_fmt_fields
!(KMerge
, heap
);
128 /// Create an iterator that merges elements of the contained iterators using
129 /// the ordering function.
131 /// Equivalent to `iterable.into_iter().kmerge()`.
134 /// use itertools::kmerge;
136 /// for elt in kmerge(vec![vec![0, 2, 4], vec![1, 3, 5], vec![6, 7]]) {
140 pub fn kmerge
<I
>(iterable
: I
) -> KMerge
<<I
::Item
as IntoIterator
>::IntoIter
>
141 where I
: IntoIterator
,
142 I
::Item
: IntoIterator
,
143 <<I
as IntoIterator
>::Item
as IntoIterator
>::Item
: PartialOrd
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 }
153 impl<I
> Clone
for KMerge
<I
>
154 where I
: Iterator
+ Clone
,
157 fn clone(&self) -> KMerge
<I
> {
158 clone_fields
!(KMerge
, self, heap
)
162 impl<I
> Iterator
for KMerge
<I
>
168 fn next(&mut self) -> Option
<Self::Item
> {
169 if self.heap
.is_empty() {
172 let result
= if let Some(next
) = self.heap
[0].next() {
175 self.heap
.swap_remove(0).head
177 sift_down(&mut self.heap
, 0, |a
, b
| a
.head
< b
.head
);
181 fn size_hint(&self) -> (usize, Option
<usize>) {
183 .map(|i
| i
.size_hint())
184 .fold1(size_hint
::add
)
185 .unwrap_or((0, Some(0)))
189 /// An iterator adaptor that merges an abitrary number of base iterators
190 /// according to an ordering function.
192 /// Iterator element type is `I::Item`.
194 /// See [`.kmerge_by()`](../trait.Itertools.html#method.kmerge_by) for more
196 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
197 pub struct KMergeBy
<I
, F
>
200 heap
: Vec
<HeadTail
<I
>>,
204 impl<I
, F
> fmt
::Debug
for KMergeBy
<I
, F
>
205 where I
: Iterator
+ fmt
::Debug
,
208 debug_fmt_fields
!(KMergeBy
, heap
);
211 /// Create an iterator that merges elements of the contained iterators.
213 /// Equivalent to `iterable.into_iter().kmerge_by(less_than)`.
214 pub fn kmerge_by
<I
, F
>(iterable
: I
, mut less_than
: F
)
215 -> KMergeBy
<<I
::Item
as IntoIterator
>::IntoIter
, F
>
216 where I
: IntoIterator
,
217 I
::Item
: IntoIterator
,
218 F
: FnMut(&<<I
as IntoIterator
>::Item
as IntoIterator
>::Item
,
219 &<<I
as IntoIterator
>::Item
as IntoIterator
>::Item
) -> bool
221 let iter
= iterable
.into_iter();
222 let (lower
, _
) = iter
.size_hint();
223 let mut heap
: Vec
<_
> = Vec
::with_capacity(lower
);
224 heap
.extend(iter
.filter_map(|it
| HeadTail
::new(it
.into_iter())));
225 heapify(&mut heap
, |a
, b
| less_than(&a
.head
, &b
.head
));
226 KMergeBy { heap: heap, less_than: less_than }
230 impl<I
, F
> Iterator
for KMergeBy
<I
, F
>
232 F
: FnMut(&I
::Item
, &I
::Item
) -> bool
236 fn next(&mut self) -> Option
<Self::Item
> {
237 if self.heap
.is_empty() {
240 let result
= if let Some(next
) = self.heap
[0].next() {
243 self.heap
.swap_remove(0).head
245 let less_than
= &mut self.less_than
;
246 sift_down(&mut self.heap
, 0, |a
, b
| less_than(&a
.head
, &b
.head
));
250 fn size_hint(&self) -> (usize, Option
<usize>) {
252 .map(|i
| i
.size_hint())
253 .fold1(size_hint
::add
)
254 .unwrap_or((0, Some(0)))