/rust/registry/src/index.crates.io-6f17d22bba15001f/itertools-0.11.0/src/minmax.rs
Line | Count | Source (jump to first uncovered line) |
1 | | |
2 | | /// `MinMaxResult` is an enum returned by `minmax`. |
3 | | /// |
4 | | /// See [`.minmax()`](crate::Itertools::minmax) for more detail. |
5 | | #[derive(Copy, Clone, PartialEq, Debug)] |
6 | | pub enum MinMaxResult<T> { |
7 | | /// Empty iterator |
8 | | NoElements, |
9 | | |
10 | | /// Iterator with one element, so the minimum and maximum are the same |
11 | | OneElement(T), |
12 | | |
13 | | /// More than one element in the iterator, the first element is not larger |
14 | | /// than the second |
15 | | MinMax(T, T) |
16 | | } |
17 | | |
18 | | impl<T: Clone> MinMaxResult<T> { |
19 | | /// `into_option` creates an `Option` of type `(T, T)`. The returned `Option` |
20 | | /// has variant `None` if and only if the `MinMaxResult` has variant |
21 | | /// `NoElements`. Otherwise `Some((x, y))` is returned where `x <= y`. |
22 | | /// If the `MinMaxResult` has variant `OneElement(x)`, performing this |
23 | | /// operation will make one clone of `x`. |
24 | | /// |
25 | | /// # Examples |
26 | | /// |
27 | | /// ``` |
28 | | /// use itertools::MinMaxResult::{self, NoElements, OneElement, MinMax}; |
29 | | /// |
30 | | /// let r: MinMaxResult<i32> = NoElements; |
31 | | /// assert_eq!(r.into_option(), None); |
32 | | /// |
33 | | /// let r = OneElement(1); |
34 | | /// assert_eq!(r.into_option(), Some((1, 1))); |
35 | | /// |
36 | | /// let r = MinMax(1, 2); |
37 | | /// assert_eq!(r.into_option(), Some((1, 2))); |
38 | | /// ``` |
39 | 0 | pub fn into_option(self) -> Option<(T,T)> { |
40 | 0 | match self { |
41 | 0 | MinMaxResult::NoElements => None, |
42 | 0 | MinMaxResult::OneElement(x) => Some((x.clone(), x)), |
43 | 0 | MinMaxResult::MinMax(x, y) => Some((x, y)) |
44 | | } |
45 | 0 | } |
46 | | } |
47 | | |
48 | | /// Implementation guts for `minmax` and `minmax_by_key`. |
49 | 0 | pub fn minmax_impl<I, K, F, L>(mut it: I, mut key_for: F, |
50 | 0 | mut lt: L) -> MinMaxResult<I::Item> |
51 | 0 | where I: Iterator, |
52 | 0 | F: FnMut(&I::Item) -> K, |
53 | 0 | L: FnMut(&I::Item, &I::Item, &K, &K) -> bool, |
54 | 0 | { |
55 | 0 | let (mut min, mut max, mut min_key, mut max_key) = match it.next() { |
56 | 0 | None => return MinMaxResult::NoElements, |
57 | 0 | Some(x) => { |
58 | 0 | match it.next() { |
59 | 0 | None => return MinMaxResult::OneElement(x), |
60 | 0 | Some(y) => { |
61 | 0 | let xk = key_for(&x); |
62 | 0 | let yk = key_for(&y); |
63 | 0 | if !lt(&y, &x, &yk, &xk) {(x, y, xk, yk)} else {(y, x, yk, xk)} |
64 | | } |
65 | | } |
66 | | } |
67 | | }; |
68 | | |
69 | | loop { |
70 | | // `first` and `second` are the two next elements we want to look |
71 | | // at. We first compare `first` and `second` (#1). The smaller one |
72 | | // is then compared to current minimum (#2). The larger one is |
73 | | // compared to current maximum (#3). This way we do 3 comparisons |
74 | | // for 2 elements. |
75 | 0 | let first = match it.next() { |
76 | 0 | None => break, |
77 | 0 | Some(x) => x |
78 | | }; |
79 | 0 | let second = match it.next() { |
80 | | None => { |
81 | 0 | let first_key = key_for(&first); |
82 | 0 | if lt(&first, &min, &first_key, &min_key) { |
83 | 0 | min = first; |
84 | 0 | } else if !lt(&first, &max, &first_key, &max_key) { |
85 | 0 | max = first; |
86 | 0 | } |
87 | 0 | break; |
88 | | } |
89 | 0 | Some(x) => x |
90 | 0 | }; |
91 | 0 | let first_key = key_for(&first); |
92 | 0 | let second_key = key_for(&second); |
93 | 0 | if !lt(&second, &first, &second_key, &first_key) { |
94 | 0 | if lt(&first, &min, &first_key, &min_key) { |
95 | 0 | min = first; |
96 | 0 | min_key = first_key; |
97 | 0 | } |
98 | 0 | if !lt(&second, &max, &second_key, &max_key) { |
99 | 0 | max = second; |
100 | 0 | max_key = second_key; |
101 | 0 | } |
102 | | } else { |
103 | 0 | if lt(&second, &min, &second_key, &min_key) { |
104 | 0 | min = second; |
105 | 0 | min_key = second_key; |
106 | 0 | } |
107 | 0 | if !lt(&first, &max, &first_key, &max_key) { |
108 | 0 | max = first; |
109 | 0 | max_key = first_key; |
110 | 0 | } |
111 | | } |
112 | | } |
113 | | |
114 | 0 | MinMaxResult::MinMax(min, max) |
115 | 0 | } |