about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorblake2-ppc <blake2-ppc>2013-08-08 22:07:21 +0200
committerblake2-ppc <blake2-ppc>2013-08-08 22:07:21 +0200
commit5d9fd882b7ebb911daf0f21ca81f4acc599c2686 (patch)
treeda9a5ac786a286381ad6b0204dea4f1cfecddc8e /src/libstd
parent98ec79c9576052d9fededd3b72b47d387c1c455d (diff)
downloadrust-5d9fd882b7ebb911daf0f21ca81f4acc599c2686.tar.gz
rust-5d9fd882b7ebb911daf0f21ca81f4acc599c2686.zip
Add std::iterator::order with lexical ordering functions for sequences
Use Eq + Ord for lexicographical ordering of sequences.

For each of <, <=, >= or > as R, use::

    [x, ..xs] R [y, ..ys]  =  if x != y { x R y } else { xs R ys }

Previous code using `a < b` and then `!(b < a)` for short-circuiting
fails on cases such as  [1.0, 2.0] < [0.0/0.0, 3.0], where the first
element was effectively considered equal.
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/iterator.rs110
1 files changed, 110 insertions, 0 deletions
diff --git a/src/libstd/iterator.rs b/src/libstd/iterator.rs
index 29f54bd10fb..3d56149fdba 100644
--- a/src/libstd/iterator.rs
+++ b/src/libstd/iterator.rs
@@ -1591,6 +1591,116 @@ impl<A: Clone> RandomAccessIterator<A> for Repeat<A> {
     fn idx(&self, _: uint) -> Option<A> { Some(self.element.clone()) }
 }
 
+/// Functions for lexicographical ordering of sequences.
+///
+/// Lexicographical ordering through `<`, `<=`, `>=`, `>` requires
+/// that the elements implement both `Eq` and `Ord`.
+///
+/// If two sequences are equal up until the point where one ends,
+/// the shorter sequence compares less.
+pub mod order {
+    use cmp;
+    use cmp::{TotalEq, TotalOrd, Ord, Eq};
+    use option::{Some, None};
+    use super::Iterator;
+
+    /// Compare `a` and `b` for equality using `TotalOrd`
+    pub fn equals<A: TotalEq, T: Iterator<A>>(mut a: T, mut b: T) -> bool {
+        loop {
+            match (a.next(), b.next()) {
+                (None, None) => return true,
+                (None, _) | (_, None) => return false,
+                (Some(x), Some(y)) => if !x.equals(&y) { return false },
+            }
+        }
+    }
+
+    /// Order `a` and `b` lexicographically using `TotalOrd`
+    pub fn cmp<A: TotalOrd, T: Iterator<A>>(mut a: T, mut b: T) -> cmp::Ordering {
+        loop {
+            match (a.next(), b.next()) {
+                (None, None) => return cmp::Equal,
+                (None, _   ) => return cmp::Less,
+                (_   , None) => return cmp::Greater,
+                (Some(x), Some(y)) => match x.cmp(&y) {
+                    cmp::Equal => (),
+                    non_eq => return non_eq,
+                },
+            }
+        }
+    }
+
+    /// Compare `a` and `b` for equality (Using partial equality, `Eq`)
+    pub fn eq<A: Eq, T: Iterator<A>>(mut a: T, mut b: T) -> bool {
+        loop {
+            match (a.next(), b.next()) {
+                (None, None) => return true,
+                (None, _) | (_, None) => return false,
+                (Some(x), Some(y)) => if !x.eq(&y) { return false },
+            }
+        }
+    }
+
+    /// Compare `a` and `b` for nonequality (Using partial equality, `Eq`)
+    pub fn ne<A: Eq, T: Iterator<A>>(mut a: T, mut b: T) -> bool {
+        loop {
+            match (a.next(), b.next()) {
+                (None, None) => return false,
+                (None, _) | (_, None) => return true,
+                (Some(x), Some(y)) => if x.ne(&y) { return true },
+            }
+        }
+    }
+
+    /// Return `a` < `b` lexicographically (Using partial order, `Ord`)
+    pub fn lt<A: Eq + Ord, T: Iterator<A>>(mut a: T, mut b: T) -> bool {
+        loop {
+            match (a.next(), b.next()) {
+                (None, None) => return false,
+                (None, _   ) => return true,
+                (_   , None) => return false,
+                (Some(x), Some(y)) => if x.ne(&y) { return x.lt(&y) },
+            }
+        }
+    }
+
+    /// Return `a` <= `b` lexicographically (Using partial order, `Ord`)
+    pub fn le<A: Eq + Ord, T: Iterator<A>>(mut a: T, mut b: T) -> bool {
+        loop {
+            match (a.next(), b.next()) {
+                (None, None) => return true,
+                (None, _   ) => return true,
+                (_   , None) => return false,
+                (Some(x), Some(y)) => if x.ne(&y) { return x.le(&y) },
+            }
+        }
+    }
+
+    /// Return `a` > `b` lexicographically (Using partial order, `Ord`)
+    pub fn gt<A: Eq + Ord, T: Iterator<A>>(mut a: T, mut b: T) -> bool {
+        loop {
+            match (a.next(), b.next()) {
+                (None, None) => return false,
+                (None, _   ) => return false,
+                (_   , None) => return true,
+                (Some(x), Some(y)) => if x.ne(&y) { return x.gt(&y) },
+            }
+        }
+    }
+
+    /// Return `a` >= `b` lexicographically (Using partial order, `Ord`)
+    pub fn ge<A: Eq + Ord, T: Iterator<A>>(mut a: T, mut b: T) -> bool {
+        loop {
+            match (a.next(), b.next()) {
+                (None, None) => return true,
+                (None, _   ) => return false,
+                (_   , None) => return true,
+                (Some(x), Some(y)) => if x.ne(&y) { return x.ge(&y) },
+            }
+        }
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;