Skip to content

Commit

Permalink
auto merge of rust-lang#7414 : gifnksm/rust/max_by, r=catamorphism
Browse files Browse the repository at this point in the history
`max_by` method returns the element that gives the maximum value from the specfied function.
`max_by`/`min_by` are convenient when you want to get the value which has greatest/smallest scores.

Inspired by [ruby's Enumerable module](http://ruby-doc.org/core-2.0/Enumerable.html).
  • Loading branch information
bors committed Jun 27, 2013
2 parents 3652736 + 8edb8f6 commit 9b6dfb8
Showing 1 changed file with 62 additions and 0 deletions.
62 changes: 62 additions & 0 deletions src/libstd/iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,26 @@ pub trait IteratorUtil<A> {

/// Count the number of elements satisfying the specified predicate
fn count(&mut self, predicate: &fn(A) -> bool) -> uint;

/// Return the element that gives the maximum value from the specfied function
///
/// # Example
///
/// --- {.rust}
/// let xs = [-3, 0, 1, 5, -10];
/// assert_eq!(*xs.iter().max_by(|x| x.abs()).unwrap(), -10);
/// ---
fn max_by<B: Ord>(&mut self, f: &fn(&A) -> B) -> Option<A>;

/// Return the element that gives the minimum value from the specfied function
///
/// # Example
///
/// --- {.rust}
/// let xs = [-3, 0, 1, 5, -10];
/// assert_eq!(*xs.iter().min_by(|x| x.abs()).unwrap(), 0);
/// ---
fn min_by<B: Ord>(&mut self, f: &fn(&A) -> B) -> Option<A>;
}

/// Iterator adaptors provided for every `Iterator` implementation. The adaptor objects are also
Expand Down Expand Up @@ -519,6 +539,36 @@ impl<A, T: Iterator<A>> IteratorUtil<A> for T {
}
i
}

#[inline]
fn max_by<B: Ord>(&mut self, f: &fn(&A) -> B) -> Option<A> {
self.fold(None, |max: Option<(A, B)>, x| {
let x_val = f(&x);
match max {
None => Some((x, x_val)),
Some((y, y_val)) => if x_val > y_val {
Some((x, x_val))
} else {
Some((y, y_val))
}
}
}).map_consume(|(x, _)| x)
}

#[inline]
fn min_by<B: Ord>(&mut self, f: &fn(&A) -> B) -> Option<A> {
self.fold(None, |min: Option<(A, B)>, x| {
let x_val = f(&x);
match min {
None => Some((x, x_val)),
Some((y, y_val)) => if x_val < y_val {
Some((x, x_val))
} else {
Some((y, y_val))
}
}
}).map_consume(|(x, _)| x)
}
}

/// A trait for iterators over elements which can be added together
Expand Down Expand Up @@ -1237,4 +1287,16 @@ mod tests {
assert_eq!(xs.iter().count(|x| *x == 5), 1);
assert_eq!(xs.iter().count(|x| *x == 95), 0);
}

#[test]
fn test_max_by() {
let xs = [-3, 0, 1, 5, -10];
assert_eq!(*xs.iter().max_by(|x| x.abs()).unwrap(), -10);
}

#[test]
fn test_min_by() {
let xs = [-3, 0, 1, 5, -10];
assert_eq!(*xs.iter().min_by(|x| x.abs()).unwrap(), 0);
}
}

0 comments on commit 9b6dfb8

Please sign in to comment.