Comparison & Ordering (PartialEq, Ord)
Comparison in Rust is powered by four traits — PartialEq and Eq give you == , while PartialOrd and Ord give you < and the ability to sort.
Learn Comparison & Ordering (PartialEq, Ord) in our free Rust course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a…
Part of the free Rust course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
In this lesson you'll derive these traits, sort with sort , sort_by , and sort_by_key , use cmp and Ordering , find min / max , and see why floats are only PartialOrd .
What You'll Learn in This Lesson
1️⃣ Deriving the Comparison Traits
You rarely write comparison logic by hand. A #[derive(...)] attribute tells the compiler to generate it: PartialEq / Eq for == , and PartialOrd / Ord for < , > , and friends. Derived ordering compares fields in declaration order .
Because major is declared before minor , two versions are first compared by major ; only when those tie does minor break the tie — exactly how version numbers should sort.
2️⃣ Sorting: sort, sort_by, sort_by_key
Once a type is Ord , sort() orders a slice ascending in place. For custom orders, sort_by takes a comparator closure, and sort_by_key sorts by a key you extract from each element. Iterators also offer min and max .
3️⃣ cmp, Ordering & the Float Catch
The cmp method returns an Ordering — one of Less , Equal , or Greater — which you can match on. Floats only implement the Partial traits, so they use partial_cmp , which returns an Option<Ordering> because NaN is unordered.
Your turn. Fill in the blanks marked ___ , then run it.
Mini-Challenge: A Leaderboard
Sort a list of players by score, highest first, and print a ranked list. Run it with cargo run and check the output.
Common Errors (and the fix)
- ❌ "the trait is not implemented for " — You called sort on floats. ✅ Use sort_by(|a, b| a.total_cmp(b)) .
- ❌ "binary operation cannot be applied" — Your type lacks PartialEq . ✅ Add #[derive(PartialEq)] .
- ❌ "cannot be sorted" on a custom struct — It's not Ord . ✅ Derive Ord (and its prerequisites) or use sort_by_key .
- ❌ Surprised NaN == NaN is false — That's correct by IEEE rules. ✅ Test for NaN with x.is_nan() instead of == .
Pro Tips
- 💡 Order fields intentionally: derived Ord compares fields top-to-bottom, so put the primary sort key first.
- 💡 Prefer sort_by_key over sort_by when there's a clear key — it's clearer and computes each key once.
- 💡 Reverse cleanly: wrap the key in std::cmp::Reverse for descending order without a custom comparator.
📋 Quick Reference — Comparison & Ordering
Tool
Gives you
PartialEq / Eq
== and !=
PartialOrd / Ord
< <= > >=, sort
a.cmp(&b)
Ordering (Ord)
a.partial_cmp(&b)
Option (floats)
v.sort_by_key(..)
Sort by extracted key
Reverse(key)
Descending order
Frequently Asked Questions
🎉 Lesson Complete!
- ✅ PartialEq / Eq give == ; PartialOrd / Ord give < and sorting
- ✅ Derived Ord compares fields in declaration order
- ✅ sort , sort_by , sort_by_key , and Reverse cover any order
- ✅ Floats are only PartialOrd because NaN is unordered
- ✅ Next lesson: Checkpoint — consolidate everything you've learned so far
Practice quiz
Which traits give you the == and != operators?
- PartialOrd / Ord
- Display / Debug
- PartialEq / Eq
- Clone / Copy
Answer: PartialEq / Eq. PartialEq provides == and !=; Eq is a marker that strengthens equality to be total.
Which traits give you < <= > >= and the ability to sort?
- PartialOrd / Ord
- PartialEq / Eq
- Hash
- Default
Answer: PartialOrd / Ord. PartialOrd provides the ordering operators; Ord adds a total order needed for sort().
In what order does derived Ord compare a struct's fields?
- Alphabetically by name
- By field size
- Randomly
- In declaration order (top to bottom)
Answer: In declaration order (top to bottom). Derived Ord compares fields lexicographically in the order they are declared.
What does this print? #[derive(PartialEq,Eq,PartialOrd,Ord)] struct V { major: u32, minor: u32 } let a = V{major:1,minor:9}; let b = V{major:2,minor:0}; println!("{}", a < b);
- false
- true
- It does not compile
- Equal
Answer: true. major is compared first; 1 < 2, so a < b is true regardless of minor.
Continue this course
- Previous: Constants & Statics
- Next: Checkpoint: Rust Basics