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     /// ```
into_option(self) -> Option<(T,T)>39     pub fn into_option(self) -> Option<(T,T)> {
40         match self {
41             MinMaxResult::NoElements => None,
42             MinMaxResult::OneElement(x) => Some((x.clone(), x)),
43             MinMaxResult::MinMax(x, y) => Some((x, y))
44         }
45     }
46 }
47 
48 /// Implementation guts for `minmax` and `minmax_by_key`.
minmax_impl<I, K, F, L>(mut it: I, mut key_for: F, mut lt: L) -> MinMaxResult<I::Item> where I: Iterator, F: FnMut(&I::Item) -> K, L: FnMut(&I::Item, &I::Item, &K, &K) -> bool,49 pub fn minmax_impl<I, K, F, L>(mut it: I, mut key_for: F,
50                                mut lt: L) -> MinMaxResult<I::Item>
51     where I: Iterator,
52           F: FnMut(&I::Item) -> K,
53           L: FnMut(&I::Item, &I::Item, &K, &K) -> bool,
54 {
55     let (mut min, mut max, mut min_key, mut max_key) = match it.next() {
56         None => return MinMaxResult::NoElements,
57         Some(x) => {
58             match it.next() {
59                 None => return MinMaxResult::OneElement(x),
60                 Some(y) => {
61                     let xk = key_for(&x);
62                     let yk = key_for(&y);
63                     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         let first = match it.next() {
76             None => break,
77             Some(x) => x
78         };
79         let second = match it.next() {
80             None => {
81                 let first_key = key_for(&first);
82                 if lt(&first, &min, &first_key, &min_key) {
83                     min = first;
84                 } else if !lt(&first, &max, &first_key, &max_key) {
85                     max = first;
86                 }
87                 break;
88             }
89             Some(x) => x
90         };
91         let first_key = key_for(&first);
92         let second_key = key_for(&second);
93         if !lt(&second, &first, &second_key, &first_key) {
94             if lt(&first, &min, &first_key, &min_key) {
95                 min = first;
96                 min_key = first_key;
97             }
98             if !lt(&second, &max, &second_key, &max_key) {
99                 max = second;
100                 max_key = second_key;
101             }
102         } else {
103             if lt(&second, &min, &second_key, &min_key) {
104                 min = second;
105                 min_key = second_key;
106             }
107             if !lt(&first, &max, &first_key, &max_key) {
108                 max = first;
109                 max_key = first_key;
110             }
111         }
112     }
113 
114     MinMaxResult::MinMax(min, max)
115 }
116