iterator: Add IteratorUtil::max_by/min_by method

This commit is contained in:
gifnksm 2013-06-27 06:51:04 +09:00
parent 23fb2278c7
commit 8edb8f6d39

View File

@ -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
@ -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
@ -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);
}
}