Standard Library
class OrderedArray<T>
An array that has been sorted by one or more keys, produced by Array.orderBy and thenBy.
since 0.1.0-alpha.1linuxwindowswasm
- bases
IIterable<T>
Overview
Sorting by several keys is written as a chain: orderBy sorts by the first key, and each
thenBy sorts by one more key, but only among elements that are still tied on every earlier
key, so a later key can never reorder elements that an earlier key already separated. The sort
is stable, so elements tied on every key keep their original relative order.
An OrderedArray is a read-only result. Call toArray to get a plain Array<T>, or iterate
it directly with for. It is not created with new; start from orderBy.
Description
orderBy and thenBy sort by several keys in sequence, the way a spreadsheet sorts by one column
and then another. array.orderBy(key) sorts an Array<T> by key, a function from an element to
a value that supports <, and returns an OrderedArray<T>. Calling .thenBy(key2) on that result
sorts again by key2, but only inside groups of elements that were still tied on every earlier
key. Any number of thenBy calls can be chained:
people.orderBy((p) => p.last).thenBy((p) => p.first)
Each sort is stable: elements that tie on every key keep their order from the source array. A call
to orderBy on its own is the one-key case of the same algorithm.
thenBy exists only on OrderedArray, not on Array. That is deliberate: there is no way to write
a tie-break on an array that has not been sorted yet. To leave the wrapper, call toArray(), which
returns a plain Array<T>, or iterate the OrderedArray directly with for, since it is
iterable. length() and isEmpty() work as on an array.
Sorting never changes the source array; orderBy and thenBy follow the same value rule as the
rest of the library and return new results. You do not construct an OrderedArray yourself:
orderBy and thenBy produce it.
Sort by last name, then first name
struct Person { string last; string first; int age; }
Array<Person> people = [Person("Smith", "Zed", 40), Person("Jones", "Amy", 30), Person("Smith", "Abe", 25), Person("Jones", "Bob", 30)];
OrderedArray<Person> byName = people.orderBy((p) => p.last).thenBy((p) => p.first);
for (Person p in byName) { console.writeln("${p.last} ${p.first}"); }
console.writeln(byName.length());
Array<Person> plain = byName.toArray();
console.writeln(plain[0].first);
for (Person p in people.orderBy((p) => p.age)) { console.writeln("${p.age} ${p.first}"); }
console.writeln(people[0].first);
Jones Amy
Jones Bob
Smith Abe
Smith Zed
4
Amy
25 Abe
30 Amy
30 Bob
40 Zed
Zed
Rules
thenBybreaks ties only within runs of elements equal on all earlier keys; it never reorders elements that an earlier key already separated.- Keys are compared with
<. A key type without<is an error when the sort is instantiated. - The sort is stable, so elements equal on every key keep their source order (
AmybeforeBobin the example above, which are tied on age). - The source
Arrayis not modified.
Examples
Ties keep source order
Array<string> words = ["pear", "fig", "apple", "kiwi", "plum"];
for (string w in words.orderBy((s) => s.length())) { console.writeln(w); }
console.writeln("--");
for (string w in words.orderBy((s) => s.length()).thenBy((s) => s)) { console.writeln(w); }
fig
pear
kiwi
plum
apple
--
fig
kiwi
pear
plum
apple
Examples
Sorting by age, then by name
Array<Pair<string, int>> people = [
Pair::Of("bob", 30), Pair::Of("amy", 25), Pair::Of("cy", 30), Pair::Of("al", 25)
];
OrderedArray<Pair<string, int>> sorted = people.orderBy((p) => p.second).thenBy((p) => p.first);
for (Pair<string, int> p in sorted) {
console.writeln("${p.second} ${p.first}");
}
console.writeln(sorted.length());
25 al
25 amy
30 bob
30 cy
4
Methods
isEmpty
isEmpty() -> boolWhether there are no elements.
Returns
true when the ordered array is empty.
Examples
Emptiness
Array<int> e = [];
console.writeln(e.orderBy((x) => x).isEmpty());
console.writeln([1].orderBy((x) => x).isEmpty());
true
false
iterator
iterator() -> IIterator<T>Return an iterator over the elements in sorted order.
A for loop over an OrderedArray uses this, so you rarely call it yourself.
Returns
An iterator positioned before the first element.
Examples
Iterating directly
Array<string> w = ["pear", "fig", "plum"];
for (string s in w.orderBy((x) => x.length())) {
console.writeln(s);
}
fig
pear
plum
length
length() -> intThe number of elements.
Returns
The element count, the same as the array that was sorted.
Examples
Counting
Array<int> a = [5, 3, 4];
console.writeln(a.orderBy((x) => x).length());
3
thenBy
thenBy<K>((T) => K key) -> OrderedArray<T>Refine the ordering by one more key, applied only to elements tied on every earlier key.
Elements that an earlier key (the orderBy key or an earlier thenBy key) already placed in
different positions are never reordered. The key type K must support <. The sort is stable,
so elements still tied afterwards keep their original relative order. The receiver is not
changed.
Parameters
- key
- Computes the next sort key of an element.
Returns
A new OrderedArray; chain further thenBy calls on it for more keys.
Examples
Length first, then alphabetical
Array<string> w = ["bb", "a", "cc", "b", "aa", "c"];
Array<string> r = w.orderBy((s) => s.length()).thenBy((s) => s).toArray();
console.writeln(r);
Array<Pair<int, int>> ps = [Pair::Of(1, 2), Pair::Of(1, 1), Pair::Of(0, 5), Pair::Of(1, 1)];
OrderedArray<Pair<int, int>> o = ps.orderBy((p) => p.first).thenBy((p) => p.second);
for (Pair<int, int> p in o) {
console.writeln("${p.first} ${p.second}");
}
[a, b, c, aa, bb, cc]
0 5
1 1
1 1
1 2
See also: orderBy
toArray
toArray() -> Array<T>The sorted elements as a plain array.
Returns
An Array<T> in the sorted order.
Examples
Back to an array
Array<int> a = [5, 3, 4];
Array<int> sorted = a.orderBy((x) => x).toArray();
console.writeln(sorted);
console.writeln(a);
[3, 4, 5]
[5, 3, 4]