more_iter/merge/
mod.rs

1#[cfg(test)] mod merge_pairs_test;
2
3pub mod merge_pairs_ext;
4
5use std::iter::Peekable;
6
7/// Merge two **sorted** [`Iterator`] of `(key, value)` pairs in **ascending** order into a single
8/// iterator. Duplicate keys are reduce by the provided `merge_value()` function.
9///
10/// The provided `merge_value(V,V)->MERGED` function determines how to merge two values with the
11/// same key.
12///
13/// # Type Parameters
14/// - `K`: The key type, which must implement [`Ord`] for ordering.
15/// - `V`: The value type.
16/// - `L`: The iterator type for the left input, where `Item = (K, V)`.
17/// - `R`: The iterator type for the right input, where `Item = (K, V)`.
18/// - `MERGED`: The merge result type. By default it is the same as `V`.
19///
20/// # Examples
21///
22/// Merge two `(key, value)` iterators by key, keeping the largest value:
23/// ```
24/// # use more_iter::MergePairs;
25/// let a = [(1, 10), (3, 30), (4, 40)];
26/// let b = [(2, 200), (3, 300)];
27///
28/// let merged = MergePairs::merge(a, Some(b), std::cmp::max).collect::<Vec<_>>();
29/// assert_eq!(vec![(1, 10), (2, 200), (3, 300), (4, 40)], merged);
30/// ```
31pub struct MergePairs<K, V, L, R, MERGED = V>
32where
33    K: Ord,
34    L: Iterator<Item = (K, V)>,
35    R: Iterator<Item = (K, V)>,
36{
37    left: Peekable<L>,
38    right: Option<Peekable<R>>,
39    merge_value: fn(V, V) -> MERGED,
40}
41
42impl<K, V, L, R, MERGED> MergePairs<K, V, L, R, MERGED>
43where
44    K: Ord,
45    L: Iterator<Item = (K, V)>,
46    R: Iterator<Item = (K, V)>,
47{
48    /// Creates a new `Merge` instance that merges the `left` and `right` iterators.
49    ///
50    /// The `merge` function is used to decide which value to keep when duplicate keys are
51    /// encountered.
52    pub fn merge<IL, IR>(left: IL, right: Option<IR>, merge_value: fn(V, V) -> MERGED) -> Self
53    where
54        IL: IntoIterator<Item = (K, V), IntoIter = L>,
55        IR: IntoIterator<Item = (K, V), IntoIter = R>,
56    {
57        MergePairs {
58            left: left.into_iter().peekable(),
59            right: right.map(|x| x.into_iter().peekable()),
60            merge_value,
61        }
62    }
63}
64
65impl<K, V, L, MERGED> MergePairs<K, V, L, L, MERGED>
66where
67    K: Ord,
68    L: Iterator<Item = (K, V)>,
69{
70    /// Creates a new `Merge` instance that merges the `left` and `right` iterators.
71    ///
72    /// The `merge` function is used to decide which value to keep when duplicate keys are
73    /// encountered.
74    pub fn single<IL, IR>(left: IL, merge_value: fn(V, V) -> MERGED) -> Self
75    where IL: IntoIterator<Item = (K, V), IntoIter = L> {
76        MergePairs {
77            left: left.into_iter().peekable(),
78            right: None,
79            merge_value,
80        }
81    }
82}
83
84impl<K, V, L, R> Iterator for MergePairs<K, V, L, R>
85where
86    K: Ord,
87    L: Iterator<Item = (K, V)>,
88    R: Iterator<Item = (K, V)>,
89{
90    type Item = (K, V);
91
92    fn next(&mut self) -> Option<Self::Item> {
93        let right = if let Some(right) = &mut self.right {
94            right
95        } else {
96            return self.left.next();
97        };
98
99        // Left iterator is exhausted, return right iterator
100        let left_key = if let Some((k, _)) = self.left.peek() {
101            k
102        } else {
103            return right.next();
104        };
105
106        // Right iterator is exhausted, return left iterator
107        let right_key = if let Some((k, _)) = right.peek() {
108            k
109        } else {
110            return self.left.next();
111        };
112
113        // Both iterators have values, return the one with smaller key
114
115        if left_key < right_key {
116            return self.left.next();
117        }
118
119        if left_key > right_key {
120            return right.next();
121        }
122
123        // Same key, merge the values
124
125        let (k, left_value): (K, V) = self.left.next().unwrap();
126        let (_, right_value): (K, V) = right.next().unwrap();
127
128        let v = (self.merge_value)(left_value, right_value);
129        Some((k, v))
130    }
131}