7 releases
Uses old Rust 2015
0.1.0 | Aug 11, 2016 |
---|---|
0.0.6 | Apr 7, 2015 |
0.0.4 | Mar 9, 2015 |
0.0.3 | Dec 23, 2014 |
#756 in Data structures
90,154 downloads per month
Used in 40 crates
(20 directly)
20KB
173 lines
Experimental comparators for collections to be generic over.
Documentation is available at https://contain-rs.github.io/compare/compare.
To use compare
with Cargo, add this to Cargo.toml
:
[dependencies]
compare = "0.1"
and this to the crate root:
extern crate compare;
lib.rs
:
Comparators.
A comparator is any type that implements the Compare
trait,
which imposes a total order. Its
compare
method accepts two values, which may
be of the same type or different types, and returns an ordering on them.
Comparators are useful for parameterizing the behavior of sort methods and certain data structures.
The most basic comparator is Natural
, which simply delegates
to the type's implementation of [Ord
]
(http://doc.rust-lang.org/std/cmp/trait.Ord.html):
use compare::{Compare, natural};
use std::cmp::Ordering::{Less, Equal, Greater};
let a = &1;
let b = &2;
let cmp = natural();
assert_eq!(cmp.compare(a, b), Less);
assert_eq!(cmp.compare(b, a), Greater);
assert_eq!(cmp.compare(a, a), Equal);
There are convenience methods for checking each of the six relations:
use compare::{Compare, natural};
let a = &1;
let b = &2;
let cmp = natural();
assert!(cmp.compares_lt(a, b));
assert!(cmp.compares_le(a, b));
assert!(cmp.compares_ge(b, a));
assert!(cmp.compares_gt(b, a));
assert!(cmp.compares_eq(a, a));
assert!(cmp.compares_ne(a, b));
The Compare
trait also provides default methods that
consume a comparator to produce a new one with different behavior, similar to
iterator adaptors. For
example, all comparators can be reversed:
use compare::{Compare, natural};
use std::cmp::Ordering::Greater;
let cmp = natural().rev();
assert_eq!(cmp.compare(&1, &2), Greater);
It is possible to implement a comparator that is not based on the natural ordering of
a type by using a closure of type Fn(&L, &R) -> Ordering
. For example, slices
can be compared by their length instead of their contents:
use compare::Compare;
use std::cmp::Ordering::{Less, Greater};
let a = [1, 2, 3];
let b = [4, 5];
let cmp = |l: &[i32], r: &[i32]| l.len().cmp(&r.len());
assert_eq!(cmp.compare(&a, &b), Greater);
let cmp = cmp.rev();
assert_eq!(cmp.compare(&a, &b), Less);
Comparators can be combined [lexicographically] (https://en.wikipedia.org/wiki/Lexicographical_order) in order to compare values first by one key, then, if the first keys were equal, by another:
use compare::Compare;
use std::cmp::Ordering::{Less, Equal, Greater};
struct Pet { name: &'static str, age: u8 }
let fido4 = &Pet { name: "Fido", age: 4 };
let ruff2 = &Pet { name: "Ruff", age: 2 };
let fido3 = &Pet { name: "Fido", age: 3 };
let name_cmp = |l: &Pet, r: &Pet| l.name.cmp(r.name);
assert_eq!(name_cmp.compare(fido4, ruff2), Less);
assert_eq!(name_cmp.compare(fido4, fido3), Equal);
assert_eq!(name_cmp.compare(ruff2, fido3), Greater);
let age_cmp = |l: &Pet, r: &Pet| l.age.cmp(&r.age);
assert_eq!(age_cmp.compare(fido4, ruff2), Greater);
assert_eq!(age_cmp.compare(fido4, fido3), Greater);
assert_eq!(age_cmp.compare(ruff2, fido3), Less);
let name_age_cmp = name_cmp.then(age_cmp);
assert_eq!(name_age_cmp.compare(fido4, ruff2), Less);
assert_eq!(name_age_cmp.compare(fido4, fido3), Greater);
assert_eq!(name_age_cmp.compare(ruff2, fido3), Greater);
It is often repetitive to compare two values of the same type by the same key, so the key-extraction logic can be factored out, simplifying the previous example:
use compare::{Compare, Extract};
use std::cmp::Ordering::{Less, Greater};
struct Pet { name: &'static str, age: u8 }
let fido4 = &Pet { name: "Fido", age: 4 };
let ruff2 = &Pet { name: "Ruff", age: 2 };
let fido3 = &Pet { name: "Fido", age: 3 };
let name_age_cmp = Extract::new(|p: &Pet| p.name)
.then(Extract::new(|p: &Pet| p.age));
assert_eq!(name_age_cmp.compare(fido4, ruff2), Less);
assert_eq!(name_age_cmp.compare(fido4, fido3), Greater);
assert_eq!(name_age_cmp.compare(ruff2, fido3), Greater);