/// `MinMaxResult` is an enum returned by `minmax`. /// /// See [`.minmax()`](crate::Itertools::minmax) for more detail. #[derive(Copy, Clone, PartialEq, Debug)] pub enum MinMaxResult { /// Empty iterator NoElements, /// Iterator with one element, so the minimum and maximum are the same OneElement(T), /// More than one element in the iterator, the first element is not larger /// than the second MinMax(T, T) } impl MinMaxResult { /// `into_option` creates an `Option` of type `(T, T)`. The returned `Option` /// has variant `None` if and only if the `MinMaxResult` has variant /// `NoElements`. Otherwise `Some((x, y))` is returned where `x <= y`. /// If the `MinMaxResult` has variant `OneElement(x)`, performing this /// operation will make one clone of `x`. /// /// # Examples /// /// ``` /// use itertools::MinMaxResult::{self, NoElements, OneElement, MinMax}; /// /// let r: MinMaxResult = NoElements; /// assert_eq!(r.into_option(), None); /// /// let r = OneElement(1); /// assert_eq!(r.into_option(), Some((1, 1))); /// /// let r = MinMax(1, 2); /// assert_eq!(r.into_option(), Some((1, 2))); /// ``` pub fn into_option(self) -> Option<(T,T)> { match self { MinMaxResult::NoElements => None, MinMaxResult::OneElement(x) => Some((x.clone(), x)), MinMaxResult::MinMax(x, y) => Some((x, y)) } } } /// Implementation guts for `minmax` and `minmax_by_key`. pub fn minmax_impl(mut it: I, mut key_for: F, mut lt: L) -> MinMaxResult where I: Iterator, F: FnMut(&I::Item) -> K, L: FnMut(&I::Item, &I::Item, &K, &K) -> bool, { let (mut min, mut max, mut min_key, mut max_key) = match it.next() { None => return MinMaxResult::NoElements, Some(x) => { match it.next() { None => return MinMaxResult::OneElement(x), Some(y) => { let xk = key_for(&x); let yk = key_for(&y); if !lt(&y, &x, &yk, &xk) {(x, y, xk, yk)} else {(y, x, yk, xk)} } } } }; loop { // `first` and `second` are the two next elements we want to look // at. We first compare `first` and `second` (#1). The smaller one // is then compared to current minimum (#2). The larger one is // compared to current maximum (#3). This way we do 3 comparisons // for 2 elements. let first = match it.next() { None => break, Some(x) => x }; let second = match it.next() { None => { let first_key = key_for(&first); if lt(&first, &min, &first_key, &min_key) { min = first; } else if !lt(&first, &max, &first_key, &max_key) { max = first; } break; } Some(x) => x }; let first_key = key_for(&first); let second_key = key_for(&second); if !lt(&second, &first, &second_key, &first_key) { if lt(&first, &min, &first_key, &min_key) { min = first; min_key = first_key; } if !lt(&second, &max, &second_key, &max_key) { max = second; max_key = second_key; } } else { if lt(&second, &min, &second_key, &min_key) { min = second; min_key = second_key; } if !lt(&first, &max, &first_key, &max_key) { max = first; max_key = first_key; } } } MinMaxResult::MinMax(min, max) }