Skip to content

Implement minmax function #11767

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 6 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions src/libstd/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -882,6 +882,16 @@ pub trait OrdIterator<A> {
/// assert!(a.iter().min().unwrap() == &1);
/// ```
fn min(&mut self) -> Option<A>;

/// `minmax` consumes the entire iterator to return
/// the mininum and maximum elements in the vector.
/// The return type `MinMax` is an enum of three variants.
/// `NoElements` is returned if the iterator `minmax` operates on is empty.
/// `OneElement(x)` is returned if the iterator `minmax` operates on has exactly one element;
/// `x` takes the value of that argument.
/// Otherwise, `MinMax(x, y)` is returned, where x <= y; x == y happens if and only if
/// the vector has more than one element and all elements are equal.
fn minmax(&mut self) -> MinMax<A>;
}

impl<A: Ord, T: Iterator<A>> OrdIterator<A> for T {
Expand All @@ -904,6 +914,59 @@ impl<A: Ord, T: Iterator<A>> OrdIterator<A> for T {
}
})
}

fn minmax(&mut self) -> MinMax<A> {
let (mut min, mut max) = match self.next() {
None => return NoElements,
Some(x) => {
match self.next() {
None => return OneElement(x),
Some(y) => if x < y {(x, y)} else {(y,x)}
}
}
};

let left_over;
loop {
let first = match self.next() {
None => {left_over = None; break;}
Some(x) => x
};
let second = match self.next() {
None => {left_over = Some(first); break;}
Some(x) => x
};
if first < second {
if first < min {min = first;}
if max < second {max = second;}
} else {
if second < min {min = second;}
if max < first {max = first;}
}
}

match left_over {
None => {}
Some(x) => {
if x < min {min = x;}
else if x > max {max = x;}
}
}

MinMax(min, max)
}
}

/// `MinMax` is an enum returned by `minmax`. See `OrdIterator::minmax` for more detail.
pub enum MinMax<T> {
/// 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)
}

/// A trait for iterators that are cloneable.
Expand Down Expand Up @@ -2943,4 +3006,37 @@ mod tests {
it.next();
assert!( it.is_empty() );
}

#[test]
fn test_minmax() {
let v: [int, ..0] = [];
match v.iter().minmax() {
NoElements => {}
_ => fail!()
}

let v = [1i];
match v.iter().minmax() {
OneElement(x) => {assert_eq!(x, &1)}
_ => fail!()
}

let v = [1i, 2, 3, 4, 5];
match v.iter().minmax() {
MinMax(x, y) => {assert_eq!(x, &1); assert_eq!(y, &5)}
_ => fail!()
}

let v = [1i, 2, 3, 4, 5, 6];
match v.iter().minmax() {
MinMax(x, y) => {assert_eq!(x, &1); assert_eq!(y, &6)}
_ => fail!()
}

let v = [1i, 1, 1, 1];
match v.iter().minmax() {
MinMax(x, y) => {assert_eq!(x, &1); assert_eq!(y, &1)}
_ => fail!()
}
}
}