UXSortDescriptor
UXSortDescriptor orders an array of objects that answer
UXEvaluable, the same protocol
UXPredicate filters on.
#use <UXKit> // or #import "UXSortDescriptor.xc"Overview
Section titled “Overview”UXSortDescriptor.make((u8*)"name", true).sort(rows); // A → ZUXSortDescriptor.make((u8*)"name", false).sort(rows); // Z → AUXSortDescriptor.numericKey((u8*)"size", true).sort(rows); // 3, 9, 20, 100Filter with a predicate, then sort with one of these. A table or list view does
this to its rows. It works on your objects, which only need to implement
valueForKey.
Values are strings, so numbers need saying so
Section titled “Values are strings, so numbers need saying so”valueForKey returns text, which lets one protocol serve filtering, sorting and
display. As a result, a numeric column must be declared:
"size as text: Alpha(100) charlie(20) bravo(3) delta(9)""size numeric: bravo(3) delta(9) charlie(20) Alpha(100)"A string sort of "100", "20", "3" orders them lexically (1 before
2 before 3), which gives the familiar wrong-looking file listing.
numericKey reads each value as an integer instead.
Comparison is by byte
Section titled “Comparison is by byte”by name asc: Alpha bravo charlie deltaAlpha comes first because A (65) is below b (98). The comparison is a
plain byte comparison, with no case folding, locale or accent handling.
For a user-visible list this is often wrong. To fix it, sort on a key your
object computes: return a lowercased copy from valueForKey for a
"name_sort" key, and sort on that. The descriptor stays simple and the
normalisation lives with the data.
UTF-8 also sorts by byte, which puts every multi-byte character after every ASCII one. The order is consistent and deterministic, but not alphabetical in any language.
An unknown key leaves the order alone
Section titled “An unknown key leaves the order alone”UXSortDescriptor.make((u8*)"nope", true).sort(rows); // unchangedvalueForKey is expected to return "" for a key it does not know, so every
row compares equal and nothing moves. A typo in a key name gives a sort that
silently does nothing, not an error. Check the key name when a column header
stops working.
The sort is selection sort, and not stable
Section titled “The sort is selection sort, and not stable”sort is a selection sort in place: O(n²) comparisons, and each comparison
calls valueForKey twice.
This suits list-view-sized data (a few hundred rows) and needs no extra
allocation. It is the wrong choice for thousands of rows, especially with an
expensive valueForKey.
Topics
Section titled “Topics”make · numericKey · compare · sort
static UXSortDescriptor* make(u8* key, bool ascending)Compare the key’s value as text. The key is kept, not copied, so pass a literal.
numericKey
Section titled “numericKey”static UXSortDescriptor* numericKey(u8* key, bool ascending)Compare as an integer.
compare
Section titled “compare”i32 compare(UXEvaluable* a, UXEvaluable* b)-1, 0 or 1, already honouring numeric and ascending. Descending
returns the opposite sign; the caller does not flip it.
Use it directly to merge two already-sorted lists, or to insert one row into a sorted array without re-sorting.
void sort(Array<UXEvaluable>* items)Order the array in place. Null values are treated as "", so a row with a
missing value sorts first ascending instead of crashing.
Fields
Section titled “Fields”key / ascending / numeric
Section titled “key / ascending / numeric”u8* keybool ascendingbool numericReadable and writable, so a column header click can flip ascending on an
existing descriptor instead of making a new one.
Example
Section titled “Example”unsorted: delta(9) Alpha(100) charlie(20) bravo(3)by name asc: Alpha(100) bravo(3) charlie(20) delta(9)by name desc: delta(9) charlie(20) bravo(3) Alpha(100)size as text: Alpha(100) charlie(20) bravo(3) delta(9)size numeric: bravo(3) delta(9) charlie(20) Alpha(100)unknown key: delta(9) Alpha(100) charlie(20) bravo(3)compare bravo vs delta: -1The program is website/site/examples/uxkit/records.xc; the doc-examples
gate compiles it, and the output above is its real output.
Conforms to
Section titled “Conforms to”- A plain class (not an
Objectsubclass)
See also
Section titled “See also”UXPredicate: filtering, the other halfUXEvaluable: the one method your objects implementUXTableView: the click-to-sort column header this sits behind