about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorgifnksm <makoto.nksm+github@gmail.com>2013-06-27 06:51:04 +0900
committergifnksm <makoto.nksm+github@gmail.com>2013-06-27 06:55:22 +0900
commit8edb8f6d39498476f1124ce1bb5bb4e094bde43f (patch)
tree281bff294e7145b952774aedb60e3b7179c2e660 /src/libstd
parent23fb2278c7c50cf5785b1c109bc399bf87fdd542 (diff)
downloadrust-8edb8f6d39498476f1124ce1bb5bb4e094bde43f.tar.gz
rust-8edb8f6d39498476f1124ce1bb5bb4e094bde43f.zip
iterator: Add `IteratorUtil::max_by/min_by` method
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/iterator.rs62
1 files changed, 62 insertions, 0 deletions
diff --git a/src/libstd/iterator.rs b/src/libstd/iterator.rs
index ab433a9a79d..9e434272198 100644
--- a/src/libstd/iterator.rs
+++ b/src/libstd/iterator.rs
@@ -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);
+    }
 }