@@ -882,6 +882,39 @@ pub trait OrdIterator<A> {
882
882
/// assert!(a.iter().min().unwrap() == &1);
883
883
/// ```
884
884
fn min ( & mut self ) -> Option < A > ;
885
+
886
+ /// `min_max` finds the mininum and maximum elements in the iterator.
887
+ ///
888
+ /// The return type `MinMaxResult` is an enum of three variants:
889
+ /// - `NoElements` if the iterator is empty.
890
+ /// - `OneElement(x)` if the iterator has exactly one element.
891
+ /// - `MinMax(x, y)` is returned otherwise, where `x <= y`. Two values are equal if and only if
892
+ /// there is more than one element in the iterator and all elements are equal.
893
+ ///
894
+ /// On an iterator of length `n`, `min_max` does `1.5 * n` comparisons,
895
+ /// and so faster than calling `min` and `max separately which does `2 * n` comparisons.
896
+ ///
897
+ /// # Example
898
+ ///
899
+ /// ```rust
900
+ /// use std::iter::{NoElements, OneElement, MinMax};
901
+ ///
902
+ /// let v: [int, ..0] = [];
903
+ /// assert_eq!(v.iter().min_max(), NoElements);
904
+ ///
905
+ /// let v = [1i];
906
+ /// assert!(v.iter().min_max() == OneElement(&1));
907
+ ///
908
+ /// let v = [1i, 2, 3, 4, 5];
909
+ /// assert!(v.iter().min_max() == MinMax(&1, &5));
910
+ ///
911
+ /// let v = [1i, 2, 3, 4, 5, 6];
912
+ /// assert!(v.iter().min_max() == MinMax(&1, &6));
913
+ ///
914
+ /// let v = [1i, 1, 1, 1];
915
+ /// assert!(v.iter().min_max() == MinMax(&1, &1));
916
+ /// ```
917
+ fn min_max ( & mut self ) -> MinMaxResult < A > ;
885
918
}
886
919
887
920
impl < A : Ord , T : Iterator < A > > OrdIterator < A > for T {
@@ -904,6 +937,91 @@ impl<A: Ord, T: Iterator<A>> OrdIterator<A> for T {
904
937
}
905
938
} )
906
939
}
940
+
941
+ fn min_max ( & mut self ) -> MinMaxResult < A > {
942
+ let ( mut min, mut max) = match self . next ( ) {
943
+ None => return NoElements ,
944
+ Some ( x) => {
945
+ match self . next ( ) {
946
+ None => return OneElement ( x) ,
947
+ Some ( y) => if x < y { ( x, y) } else { ( y, x) }
948
+ }
949
+ }
950
+ } ;
951
+
952
+ loop {
953
+ // `first` and `second` are the two next elements we want to look at.
954
+ // We first compare `first` and `second` (#1). The smaller one is then compared to
955
+ // current mininum (#2). The larger one is compared to current maximum (#3). This
956
+ // way we do 3 comparisons for 2 elements.
957
+ let first = match self . next ( ) {
958
+ None => break ,
959
+ Some ( x) => x
960
+ } ;
961
+ let second = match self . next ( ) {
962
+ None => {
963
+ if first < min {
964
+ min = first;
965
+ } else if first > max {
966
+ max = first;
967
+ }
968
+ break ;
969
+ }
970
+ Some ( x) => x
971
+ } ;
972
+ if first < second {
973
+ if first < min { min = first; }
974
+ if max < second { max = second; }
975
+ } else {
976
+ if second < min { min = second; }
977
+ if max < first { max = first; }
978
+ }
979
+ }
980
+
981
+ MinMax ( min, max)
982
+ }
983
+ }
984
+
985
+ /// `MinMaxResult` is an enum returned by `min_max`. See `OrdIterator::min_max` for more detail.
986
+ #[ deriving( Clone , Eq ) ]
987
+ pub enum MinMaxResult < T > {
988
+ /// Empty iterator
989
+ NoElements ,
990
+
991
+ /// Iterator with one element, so the minimum and maximum are the same
992
+ OneElement ( T ) ,
993
+
994
+ /// More than one element in the iterator, the first element is not larger than the second
995
+ MinMax ( T , T )
996
+ }
997
+
998
+ impl < T : Clone > MinMaxResult < T > {
999
+ /// `into_option` creates an `Option` of type `(T,T)`. The returned `Option` has variant
1000
+ /// `None` if and only if the `MinMaxResult` has variant `NoElements`. Otherwise variant
1001
+ /// `Some(x,y)` is returned where `x <= y`. If `MinMaxResult` has variant `OneElement(x)`,
1002
+ /// performing this operation will make one clone of `x`.
1003
+ ///
1004
+ /// # Example
1005
+ ///
1006
+ /// ```rust
1007
+ /// use std::iter::{NoElements, OneElement, MinMax, MinMaxResult};
1008
+ ///
1009
+ /// let r: MinMaxResult<int> = NoElements;
1010
+ /// assert_eq!(r.into_option(), None)
1011
+ ///
1012
+ /// let r = OneElement(1);
1013
+ /// assert_eq!(r.into_option(), Some((1,1)));
1014
+ ///
1015
+ /// let r = MinMax(1,2);
1016
+ /// assert_eq!(r.into_option(), Some((1,2)));
1017
+ /// ```
1018
+ pub fn into_option ( self ) -> Option < ( T , T ) > {
1019
+ match self {
1020
+ NoElements => None ,
1021
+ OneElement ( x) => Some ( ( x. clone ( ) , x) ) ,
1022
+ MinMax ( x, y) => Some ( ( x, y) )
1023
+ }
1024
+ }
907
1025
}
908
1026
909
1027
/// A trait for iterators that are cloneable.
@@ -2944,4 +3062,34 @@ mod tests {
2944
3062
it. next ( ) ;
2945
3063
assert ! ( it. is_empty( ) ) ;
2946
3064
}
3065
+
3066
+ #[ test]
3067
+ fn test_min_max ( ) {
3068
+ let v: [ int , ..0 ] = [ ] ;
3069
+ assert_eq ! ( v. iter( ) . min_max( ) , NoElements ) ;
3070
+
3071
+ let v = [ 1 i] ;
3072
+ assert ! ( v. iter( ) . min_max( ) == OneElement ( & 1 ) ) ;
3073
+
3074
+ let v = [ 1 i, 2 , 3 , 4 , 5 ] ;
3075
+ assert ! ( v. iter( ) . min_max( ) == MinMax ( & 1 , & 5 ) ) ;
3076
+
3077
+ let v = [ 1 i, 2 , 3 , 4 , 5 , 6 ] ;
3078
+ assert ! ( v. iter( ) . min_max( ) == MinMax ( & 1 , & 6 ) ) ;
3079
+
3080
+ let v = [ 1 i, 1 , 1 , 1 ] ;
3081
+ assert ! ( v. iter( ) . min_max( ) == MinMax ( & 1 , & 1 ) ) ;
3082
+ }
3083
+
3084
+ #[ test]
3085
+ fn test_MinMaxResult ( ) {
3086
+ let r: MinMaxResult < int > = NoElements ;
3087
+ assert_eq ! ( r. into_option( ) , None )
3088
+
3089
+ let r = OneElement ( 1 ) ;
3090
+ assert_eq ! ( r. into_option( ) , Some ( ( 1 , 1 ) ) ) ;
3091
+
3092
+ let r = MinMax ( 1 , 2 ) ;
3093
+ assert_eq ! ( r. into_option( ) , Some ( ( 1 , 2 ) ) ) ;
3094
+ }
2947
3095
}
0 commit comments