Ordering — Composable Comparators
Sorting a collection is straightforward when we only care about a single, simple field:
However, as soon as we need to sort across multiple criteria — say, grouping employees by department, and then sorting by salary within each department — our code quickly becomes cluttered with manual tiebreaker logic:
This code is verbose, tedious to write, and prone to copy-paste bugs. Crucially, these comparators
do not compose. You cannot take an existing byDepartment checker and a bySalary checker and
combine them into a third comparator without rewriting the nested logic from scratch.
Ordering<A> solves this problem. It represents a first-class, pure comparator:
A positive return number means the first element comes after the second; a negative number means it
comes before; and zero indicates a tie. Because Ordering matches the standard JavaScript
comparator signature, it is 100% compatible with native runtime APIs.
Built-In Ordering Instances
Section titled “Built-In Ordering Instances”The library provides optimized, built-in ordering instances for primitive types:
Reversing Sort Order: reverse
Section titled “Reversing Sort Order: reverse”Ordering.reverse flips the sorting direction of any existing comparator:
Adapting Keys: by
Section titled “Adapting Keys: by”Ordering.by adapts an ordering checker designed for a simpler type A so that it operates on a
richer type B by extracting the field to compare:
Combining Comparators: thenBy
Section titled “Combining Comparators: thenBy”Ordering.thenBy allows you to chain two ordering checkers together, using the second checker as a
tiebreaker only when the first check evaluates to a tie (0):
Practical Application: Immutable Sorting
Section titled “Practical Application: Immutable Sorting”Arr.sortWith accepts any Ordering<A> instance and returns a fresh, sorted array, avoiding
the mutability issues associated with JavaScript’s native Array.prototype.sort:
When to use Ordering
Section titled “When to use Ordering”Use Ordering when:
Section titled “Use Ordering when:”- Sorting by multiple criteria: You want to chain multiple sort keys and tiebreakers point-free.
- Executing immutable sorts: You are sorting arrays inside reactive pipelines where mutating the original source would trigger unintended rendering bugs.
- Adapting nested properties: You want to reuse core primitive comparators across complex object
shapes using
by.
Keep using standard arrow inline functions when:
Section titled “Keep using standard arrow inline functions when:”- Executing a single, local sort: You are sorting a primitive array (like numbers) within a narrow, one-off synchronous scope where structural composition is unnecessary.