PartialOrd and Ord
PartialOrd and Ord
In Rust, comparing values for ordering (less than, greater than) is done through two traits: PartialOrd and Ord. These traits are the ordering counterparts to PartialEq and Eq that you learned about for equality comparison.
PartialOrd defines a partial ordering where comparisons may not always produce a result. The classic example is floating-point numbers: comparing NaN to any value (including itself) returns None because NaN has no defined ordering. The trait requires implementing the partial_cmp method which returns Option<Ordering>.
Ord defines a total ordering where every pair of values can be compared, and the result is always Less, Equal, or Greater. Types implementing Ord must also implement PartialOrd, Eq, and PartialEq. This is the trait used for sorting, binary search, and ordered collections like BTreeMap.
Your Task
Implement the following types and functions demonstrating ordering traits:
-
Score- A struct wrapping au32that derivesPartialOrdandOrdfor natural ordering. -
Version- A struct withmajor,minor, andpatchfields (allu32). ImplementOrdmanually to compare versions semantically (major first, then minor, then patch). -
Temperature- An enum withCelsius(f64)andFahrenheit(f64)variants. ImplementPartialOrdto compare temperatures after normalizing to Celsius. This should NOT implementOrdbecause floating-point values have no total ordering (NaN). -
Priority- An enum withLow,Medium,High, andCriticalvariants. DerivePartialOrdandOrdwhere the order follows the declaration order (Low < Medium < High < Critical). -
Player- A struct withname: Stringandscore: u32. ImplementOrdto sort by score descending (higher scores first), then by name ascending as a tiebreaker. -
find_min<T: Ord>- Returns a reference to the minimum element in a non-empty slice, orNoneif empty. -
find_max<T: Ord>- Returns a reference to the maximum element in a non-empty slice, orNoneif empty. -
is_sorted<T: Ord>- Returnstrueif the slice is sorted in ascending order (each element<=the next). -
clamp<T: Ord>- Returns a value clamped between min and max bounds (inclusive). If value<min, returns min. If value>max, returns max. Otherwise returns the value itself.
Examples
use partialord_ord::*;
// Score - derived ordering
let s1 = Score(100);
let s2 = Score(200);
assert!(s1 < s2);
// Version - semantic versioning order
let v1 = Version::new(1, 9, 0);
let v2 = Version::new(2, 0, 0);
assert!(v1 < v2);
// Temperature - partial ordering across units
let t1 = Temperature::Celsius(0.0);
let t2 = Temperature::Fahrenheit(32.0); // 0°C
assert!(t1 == t2); // Equal when normalized
// Priority - enum ordering
assert!(Priority::Low < Priority::Critical);
// Player - custom ordering (score desc, name asc)
let alice = Player::new("Alice", 100);
let bob = Player::new("Bob", 100);
assert!(alice < bob); // Same score, alphabetical order
// Utility functions
assert_eq!(find_min(&[3, 1, 4, 1, 5]), Some(&1));
assert_eq!(find_max(&[3, 1, 4, 1, 5]), Some(&5));
assert!(is_sorted(&[1, 2, 3, 4, 5]));
assert_eq!(clamp(&5, &1, &10), &5);
assert_eq!(clamp(&0, &1, &10), &1);Hints
Click here to reveal hints
- Use
#[derive(PartialOrd, Ord)]for simple types where field-by-field comparison is correct. - When implementing
Ordmanually, you must implement thecmpmethod returningstd::cmp::Ordering. - The
Orderingenum has variants:Less,Equal,Greater. - For
Version, compare fields in order of importance using.cmp()and.then()or.then_with(). - For
Temperature, convert to a common unit before comparing. Remember thatpartial_cmpreturnsOption<Ordering>. - For
Playerwith descending score, reverse the comparison order for scores. - Use
.cmp()forOrdtypes and.partial_cmp()forPartialOrdtypes. - Derive macros for enums order variants by their declaration order (first variant is smallest).
Run to execute your code and see test results here.