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.
This commit is contained in:
parent
98ec79c957
commit
5d9fd882b7
@ -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::*;
|
||||
|
Loading…
x
Reference in New Issue
Block a user