Skip to content

Commit 5d9fd88

Browse files
author
blake2-ppc
committed
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.
1 parent 98ec79c commit 5d9fd88

File tree

1 file changed

+110
-0
lines changed

1 file changed

+110
-0
lines changed

src/libstd/iterator.rs

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1591,6 +1591,116 @@ impl<A: Clone> RandomAccessIterator<A> for Repeat<A> {
15911591
fn idx(&self, _: uint) -> Option<A> { Some(self.element.clone()) }
15921592
}
15931593

1594+
/// Functions for lexicographical ordering of sequences.
1595+
///
1596+
/// Lexicographical ordering through `<`, `<=`, `>=`, `>` requires
1597+
/// that the elements implement both `Eq` and `Ord`.
1598+
///
1599+
/// If two sequences are equal up until the point where one ends,
1600+
/// the shorter sequence compares less.
1601+
pub mod order {
1602+
use cmp;
1603+
use cmp::{TotalEq, TotalOrd, Ord, Eq};
1604+
use option::{Some, None};
1605+
use super::Iterator;
1606+
1607+
/// Compare `a` and `b` for equality using `TotalOrd`
1608+
pub fn equals<A: TotalEq, T: Iterator<A>>(mut a: T, mut b: T) -> bool {
1609+
loop {
1610+
match (a.next(), b.next()) {
1611+
(None, None) => return true,
1612+
(None, _) | (_, None) => return false,
1613+
(Some(x), Some(y)) => if !x.equals(&y) { return false },
1614+
}
1615+
}
1616+
}
1617+
1618+
/// Order `a` and `b` lexicographically using `TotalOrd`
1619+
pub fn cmp<A: TotalOrd, T: Iterator<A>>(mut a: T, mut b: T) -> cmp::Ordering {
1620+
loop {
1621+
match (a.next(), b.next()) {
1622+
(None, None) => return cmp::Equal,
1623+
(None, _ ) => return cmp::Less,
1624+
(_ , None) => return cmp::Greater,
1625+
(Some(x), Some(y)) => match x.cmp(&y) {
1626+
cmp::Equal => (),
1627+
non_eq => return non_eq,
1628+
},
1629+
}
1630+
}
1631+
}
1632+
1633+
/// Compare `a` and `b` for equality (Using partial equality, `Eq`)
1634+
pub fn eq<A: Eq, T: Iterator<A>>(mut a: T, mut b: T) -> bool {
1635+
loop {
1636+
match (a.next(), b.next()) {
1637+
(None, None) => return true,
1638+
(None, _) | (_, None) => return false,
1639+
(Some(x), Some(y)) => if !x.eq(&y) { return false },
1640+
}
1641+
}
1642+
}
1643+
1644+
/// Compare `a` and `b` for nonequality (Using partial equality, `Eq`)
1645+
pub fn ne<A: Eq, T: Iterator<A>>(mut a: T, mut b: T) -> bool {
1646+
loop {
1647+
match (a.next(), b.next()) {
1648+
(None, None) => return false,
1649+
(None, _) | (_, None) => return true,
1650+
(Some(x), Some(y)) => if x.ne(&y) { return true },
1651+
}
1652+
}
1653+
}
1654+
1655+
/// Return `a` < `b` lexicographically (Using partial order, `Ord`)
1656+
pub fn lt<A: Eq + Ord, T: Iterator<A>>(mut a: T, mut b: T) -> bool {
1657+
loop {
1658+
match (a.next(), b.next()) {
1659+
(None, None) => return false,
1660+
(None, _ ) => return true,
1661+
(_ , None) => return false,
1662+
(Some(x), Some(y)) => if x.ne(&y) { return x.lt(&y) },
1663+
}
1664+
}
1665+
}
1666+
1667+
/// Return `a` <= `b` lexicographically (Using partial order, `Ord`)
1668+
pub fn le<A: Eq + Ord, T: Iterator<A>>(mut a: T, mut b: T) -> bool {
1669+
loop {
1670+
match (a.next(), b.next()) {
1671+
(None, None) => return true,
1672+
(None, _ ) => return true,
1673+
(_ , None) => return false,
1674+
(Some(x), Some(y)) => if x.ne(&y) { return x.le(&y) },
1675+
}
1676+
}
1677+
}
1678+
1679+
/// Return `a` > `b` lexicographically (Using partial order, `Ord`)
1680+
pub fn gt<A: Eq + Ord, T: Iterator<A>>(mut a: T, mut b: T) -> bool {
1681+
loop {
1682+
match (a.next(), b.next()) {
1683+
(None, None) => return false,
1684+
(None, _ ) => return false,
1685+
(_ , None) => return true,
1686+
(Some(x), Some(y)) => if x.ne(&y) { return x.gt(&y) },
1687+
}
1688+
}
1689+
}
1690+
1691+
/// Return `a` >= `b` lexicographically (Using partial order, `Ord`)
1692+
pub fn ge<A: Eq + Ord, T: Iterator<A>>(mut a: T, mut b: T) -> bool {
1693+
loop {
1694+
match (a.next(), b.next()) {
1695+
(None, None) => return true,
1696+
(None, _ ) => return false,
1697+
(_ , None) => return true,
1698+
(Some(x), Some(y)) => if x.ne(&y) { return x.ge(&y) },
1699+
}
1700+
}
1701+
}
1702+
}
1703+
15941704
#[cfg(test)]
15951705
mod tests {
15961706
use super::*;

0 commit comments

Comments
 (0)