Skip to content

Commit 7d3ff90

Browse files
committed
Improve documentation of sort-related functions
In particular: * document the `order` keyword in `sort!` * list explicitly the required properties of `lt` in `sort!` * clarify the sequence of "by" transformations if both `by` and `order` are given * show default values in the signatures for `searchsorted` and related functions * add `isunordered` to the manual (it's already exported)
1 parent 9f93b31 commit 7d3ff90

File tree

5 files changed

+90
-56
lines changed

5 files changed

+90
-56
lines changed

base/operators.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -154,15 +154,17 @@ Values that are normally unordered, such as `NaN`,
154154
are ordered after regular values.
155155
[`missing`](@ref) values are ordered last.
156156
157-
This is the default comparison used by [`sort`](@ref).
157+
This is the default comparison used by [`sort!`](@ref).
158158
159159
# Implementation
160160
Non-numeric types with a total order should implement this function.
161161
Numeric types only need to implement it if they have special values such as `NaN`.
162162
Types with a partial order should implement [`<`](@ref).
163-
See the documentation on [Alternate orderings](@ref) for how to define alternate
163+
See the documentation on [Alternate Orderings](@ref) for how to define alternate
164164
ordering methods that can be used in sorting and related functions.
165165
166+
See also [`isequal`](@ref), [`isunordered`](@ref).
167+
166168
# Examples
167169
```jldoctest
168170
julia> isless(1, 3)
@@ -1344,7 +1346,7 @@ corresponding position in `collection`. To get a vector indicating whether each
13441346
in `items` is in `collection`, wrap `collection` in a tuple or a `Ref` like this:
13451347
`in.(items, Ref(collection))` or `items .∈ Ref(collection)`.
13461348
1347-
See also: [`∉`](@ref).
1349+
See also: [`∉`](@ref), [`insorted`](@ref), [`contains`](@ref), [`occursin`](@ref), [`issubset`](@ref).
13481350
13491351
# Examples
13501352
```jldoctest
@@ -1382,8 +1384,6 @@ julia> [1, 2] .∈ ([2, 3],)
13821384
0
13831385
1
13841386
```
1385-
1386-
See also: [`insorted`](@ref), [`contains`](@ref), [`occursin`](@ref), [`issubset`](@ref).
13871387
"""
13881388
in
13891389

base/sort.jl

Lines changed: 82 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ end
6464
issorted(v, lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward)
6565
6666
Test whether a vector is in sorted order. The `lt`, `by` and `rev` keywords modify what
67-
order is considered to be sorted just as they do for [`sort`](@ref).
67+
order is considered to be sorted just as they do for [`sort!`](@ref).
6868
6969
# Examples
7070
```jldoctest
@@ -94,14 +94,17 @@ maybeview(v, k) = view(v, k)
9494
maybeview(v, k::Integer) = v[k]
9595

9696
"""
97-
partialsort!(v, k; by=<transform>, lt=<comparison>, rev=false)
97+
partialsort!(v, k; by=identity, lt=isless, rev=false)
9898
99-
Partially sort the vector `v` in place, according to the order specified by `by`, `lt` and
100-
`rev` so that the value at index `k` (or range of adjacent values if `k` is a range) occurs
99+
Partially sort the vector `v` in place so that the value at index `k` (or
100+
range of adjacent values if `k` is a range) occurs
101101
at the position where it would appear if the array were fully sorted. If `k` is a single
102102
index, that value is returned; if `k` is a range, an array of values at those indices is
103103
returned. Note that `partialsort!` may not fully sort the input array.
104104
105+
For the keyword arguments, see the documentation of [`sort!`](@ref).
106+
107+
105108
# Examples
106109
```jldoctest
107110
julia> a = [1, 2, 4, 3, 4]
@@ -148,9 +151,9 @@ partialsort!(v::AbstractVector, k::Union{Integer,OrdinalRange};
148151
partialsort!(v, k, ord(lt,by,rev,order))
149152

150153
"""
151-
partialsort(v, k, by=<transform>, lt=<comparison>, rev=false)
154+
partialsort(v, k, by=identity, lt=isless, rev=false)
152155
153-
Variant of [`partialsort!`](@ref) which copies `v` before partially sorting it, thereby returning the
156+
Variant of [`partialsort!`](@ref) that copies `v` before partially sorting it, thereby returning the
154157
same thing as `partialsort!` but leaving `v` unmodified.
155158
"""
156159
partialsort(v::AbstractVector, k::Union{Integer,OrdinalRange}; kws...) =
@@ -288,14 +291,16 @@ for s in [:searchsortedfirst, :searchsortedlast, :searchsorted]
288291
end
289292

290293
"""
291-
searchsorted(a, x; by=<transform>, lt=<comparison>, rev=false)
294+
searchsorted(a, x; by=identity, lt=isless, rev=false)
292295
293-
Return the range of indices of `a` which compare as equal to `x` (using binary search)
294-
according to the order specified by the `by`, `lt` and `rev` keywords, assuming that `a`
295-
is already sorted in that order. Return an empty range located at the insertion point
296-
if `a` does not contain values equal to `x`.
296+
Return the range of indices of `a` that compare as equal to `x` (using binary
297+
search), assuming that `a` is already sorted. Return an empty range located at
298+
the insertion point if `a` does not contain values equal to `x`.
297299
298-
See also: [`insorted`](@ref), [`searchsortedfirst`](@ref), [`sort`](@ref), [`findall`](@ref).
300+
The `by`, `lt` and `rev` keywords modify what order is assumed for the data,
301+
as described in the [`sort!`](@ref) documentation.
302+
303+
See also: [`insorted`](@ref), [`searchsortedfirst`](@ref), [`sort!`](@ref), [`findall`](@ref).
299304
300305
# Examples
301306
```jldoctest
@@ -317,14 +322,17 @@ julia> searchsorted([1, 2, 4, 5, 5, 7], 0) # no match, insert at start
317322
""" searchsorted
318323

319324
"""
320-
searchsortedfirst(a, x; by=<transform>, lt=<comparison>, rev=false)
325+
searchsortedfirst(a, x; by=identity, lt=isless, rev=false)
321326
322-
Return the index of the first value in `a` greater than or equal to `x`, according to the
323-
specified order. Return `lastindex(a) + 1` if `x` is greater than all values in `a`.
324-
`a` is assumed to be sorted.
327+
Return the index of the first value in `a` greater than or equal to `x`,
328+
assuming that `a` is already sorted. Return `lastindex(a) + 1` if `x` is
329+
greater than all values in `a`.
325330
326331
`insert!`ing `x` at this index will maintain sorted order.
327332
333+
The `by`, `lt` and `rev` keywords modify what order is assumed for the data,
334+
as described in the [`sort!`](@ref) documentation.
335+
328336
See also: [`searchsortedlast`](@ref), [`searchsorted`](@ref), [`findfirst`](@ref).
329337
330338
# Examples
@@ -347,11 +355,12 @@ julia> searchsortedfirst([1, 2, 4, 5, 5, 7], 0) # no match, insert at start
347355
""" searchsortedfirst
348356

349357
"""
350-
searchsortedlast(a, x; by=<transform>, lt=<comparison>, rev=false)
358+
searchsortedlast(a, x; by=identity, lt=isless, rev=false)
351359
352-
Return the index of the last value in `a` less than or equal to `x`, according to the
353-
specified order. Return `firstindex(a) - 1` if `x` is less than all values in `a`. `a` is
354-
assumed to be sorted.
360+
Return the index of the last value in `a` less than or equal to `x`, assuming
361+
that `a` is already sorted. Return `firstindex(a) - 1` if `x` is less than all
362+
values in `a`. The `by`, `lt` and `rev` keywords modify what order is assumed
363+
for the data, as described in the [`sort!`](@ref) documentation.
355364
356365
# Examples
357366
```jldoctest
@@ -373,12 +382,12 @@ julia> searchsortedlast([1, 2, 4, 5, 5, 7], 0) # no match, insert at start
373382
""" searchsortedlast
374383

375384
"""
376-
insorted(x, a; by=<transform>, lt=<comparison>, rev=false) -> Bool
385+
insorted(x, a; by=identity, lt=isless, rev=false) -> Bool
377386
378387
Determine whether an item `x` is in the sorted collection `a`, in the sense that
379-
it is [`==`](@ref) to one of the values of the collection according to the order
380-
specified by the `by`, `lt` and `rev` keywords, assuming that `a` is already
381-
sorted in that order, see [`sort`](@ref) for the keywords.
388+
it is [`==`](@ref) to one of the values of the collection. The `by`, `lt` and
389+
`rev` keywords modify what order is assumed for the collection, as described in
390+
the [`sort!`](@ref) documentation.
382391
383392
See also [`in`](@ref).
384393
@@ -524,7 +533,7 @@ Base.size(v::WithoutMissingVector) = size(v.data)
524533
send_to_end!(f::Function, v::AbstractVector; [lo, hi])
525534
526535
Send every element of `v` for which `f` returns `true` to the end of the vector and return
527-
the index of the last element which for which `f` returns `false`.
536+
the index of the last element for which `f` returns `false`.
528537
529538
`send_to_end!(f, v, lo, hi)` is equivalent to `send_to_end!(f, view(v, lo:hi))+lo-1`
530539
@@ -724,8 +733,8 @@ Insertion sort traverses the collection one element at a time, inserting
724733
each element into its correct, sorted position in the output vector.
725734
726735
Characteristics:
727-
* *stable*: preserves the ordering of elements which compare equal
728-
(e.g. "a" and "A" in a sort of letters which ignores case).
736+
* *stable*: preserves the ordering of elements that compare equal
737+
(e.g. "a" and "A" in a sort of letters that ignores case).
729738
* *in-place* in memory.
730739
* *quadratic performance* in the number of elements to be sorted:
731740
it is well-suited to small collections but should not be used for large ones.
@@ -965,8 +974,8 @@ is treated as the first or last index of the input, respectively.
965974
`lo` and `hi` may be specified together as an `AbstractUnitRange`.
966975
967976
Characteristics:
968-
* *stable*: preserves the ordering of elements which compare equal
969-
(e.g. "a" and "A" in a sort of letters which ignores case).
977+
* *stable*: preserves the ordering of elements that compare equal
978+
(e.g. "a" and "A" in a sort of letters that ignores case).
970979
* *not in-place* in memory.
971980
* *divide-and-conquer*: sort strategy similar to [`QuickSort`](@ref).
972981
* *linear runtime* if `length(lo:hi)` is constant
@@ -1242,7 +1251,7 @@ Otherwise, we dispatch to [`InsertionSort`](@ref) for inputs with `length <= 40`
12421251
perform a presorted check ([`CheckSorted`](@ref)).
12431252
12441253
We check for short inputs before performing the presorted check to avoid the overhead of the
1245-
check for small inputs. Because the alternate dispatch is to [`InseritonSort`](@ref) which
1254+
check for small inputs. Because the alternate dispatch is to [`InsertionSort`](@ref) which
12461255
has efficient `O(n)` runtime on presorted inputs, the check is not necessary for small
12471256
inputs.
12481257
@@ -1323,15 +1332,31 @@ defalg(v::AbstractArray{Union{}}) = DEFAULT_UNSTABLE # for method disambiguation
13231332
"""
13241333
sort!(v; alg::Algorithm=defalg(v), lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward)
13251334
1326-
Sort the vector `v` in place. A stable algorithm is used by default. You can select a
1327-
specific algorithm to use via the `alg` keyword (see [Sorting Algorithms](@ref) for
1328-
available algorithms). The `by` keyword lets you provide a function that will be applied to
1329-
each element before comparison; the `lt` keyword allows providing a custom "less than"
1330-
function (note that for every `x` and `y`, only one of `lt(x,y)` and `lt(y,x)` can return
1331-
`true`); use `rev=true` to reverse the sorting order. These options are independent and can
1332-
be used together in all possible combinations: if both `by` and `lt` are specified, the `lt`
1333-
function is applied to the result of the `by` function; `rev=true` reverses whatever
1334-
ordering specified via the `by` and `lt` keywords.
1335+
Sort the vector `v` in place. A stable algorithm is used by default. A specific
1336+
algorithm can be selected via the `alg` keyword (see [Sorting Algorithms](@ref)
1337+
for available algorithms). Elements are first transformed by the function `by`
1338+
and then compared according to either the function `lt` or the ordering
1339+
`order`. Finally, the resulting order is reversed if `rev=true`.
1340+
1341+
The `lt` function should define a strict partial order, that is, it should be
1342+
1343+
- irreflexive: `lt(x, x)` always yields `false`,
1344+
- asymmetric: if `lt(x, y)` yields `true` then `lt(y, x)` yields `false`,
1345+
- transitive: `lt(x, y) && lt(y, z)` implies `lt(x, z)`.
1346+
1347+
For example `<` is a valid `lt` function but `≤` is not.
1348+
1349+
Passing an `lt` other than `isless` along with an `order` other than
1350+
[`Base.Order.Forward`](@ref) or [`Base.Order.Reverse`](@ref) is not permitted,
1351+
otherwise all options are independent and can be used together in all possible
1352+
combinations. Note that `order` can also include a "by" transformation, in
1353+
which case it is applied after that defined with the `by` keyword. For more
1354+
information on `order` values see the documentation on [Alternate
1355+
Orderings](@ref).
1356+
1357+
See also [`sort`](@ref), [`sortperm`](@ref), [`sortslices`](@ref),
1358+
[`partialsort!`](@ref), [`partialsortperm`](@ref), [`issorted`](@ref),
1359+
[`searchsorted`](@ref), [`insorted`](@ref), [`Base.Order.ord`](@ref).
13351360
13361361
# Examples
13371362
```jldoctest
@@ -1358,6 +1383,13 @@ julia> v = [(1, "c"), (3, "a"), (2, "b")]; sort!(v, by = x -> x[2]); v
13581383
(3, "a")
13591384
(2, "b")
13601385
(1, "c")
1386+
1387+
julia> sort(0:3, by=x->x-2, order=Base.Order.By(abs)) # same as sort(0:3, by=abs(x->x-2))
1388+
4-element Vector{Int64}:
1389+
2
1390+
1
1391+
3
1392+
0
13611393
```
13621394
"""
13631395
function sort!(v::AbstractVector{T};
@@ -1398,15 +1430,15 @@ sort(v::AbstractVector; kws...) = sort!(copymutable(v); kws...)
13981430
## partialsortperm: the permutation to sort the first k elements of an array ##
13991431

14001432
"""
1401-
partialsortperm(v, k; by=<transform>, lt=<comparison>, rev=false)
1433+
partialsortperm(v, k; by=ientity, lt=isless, rev=false)
14021434
14031435
Return a partial permutation `I` of the vector `v`, so that `v[I]` returns values of a fully
14041436
sorted version of `v` at index `k`. If `k` is a range, a vector of indices is returned; if
14051437
`k` is an integer, a single index is returned. The order is specified using the same
14061438
keywords as `sort!`. The permutation is stable, meaning that indices of equal elements
14071439
appear in ascending order.
14081440
1409-
Note that this function is equivalent to, but more efficient than, calling `sortperm(...)[k]`.
1441+
This function is equivalent to, but more efficient than, calling `sortperm(...)[k]`.
14101442
14111443
# Examples
14121444
```jldoctest
@@ -1432,7 +1464,7 @@ partialsortperm(v::AbstractVector, k::Union{Integer,OrdinalRange}; kwargs...) =
14321464
partialsortperm!(similar(Vector{eltype(k)}, axes(v,1)), v, k; kwargs...)
14331465

14341466
"""
1435-
partialsortperm!(ix, v, k; by=<transform>, lt=<comparison>, rev=false)
1467+
partialsortperm!(ix, v, k; by=identity, lt=isless, rev=false)
14361468
14371469
Like [`partialsortperm`](@ref), but accepts a preallocated index vector `ix` the same size as
14381470
`v`, which is used to store (a permutation of) the indices of `v`.
@@ -1732,7 +1764,8 @@ end
17321764
sort!(A; dims::Integer, alg::Algorithm=defalg(A), lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward)
17331765
17341766
Sort the multidimensional array `A` along dimension `dims`.
1735-
See [`sort!`](@ref) for a description of possible keyword arguments.
1767+
See the vector version of [`sort!`](@ref) for a description of possible keyword
1768+
arguments.
17361769
17371770
To sort slices of an array, refer to [`sortslices`](@ref).
17381771
@@ -1886,8 +1919,8 @@ algorithm. Partial quick sort returns the smallest `k` elements sorted from smal
18861919
to largest, finding them and sorting them using [`QuickSort`](@ref).
18871920
18881921
Characteristics:
1889-
* *not stable*: does not preserve the ordering of elements which
1890-
compare equal (e.g. "a" and "A" in a sort of letters which
1922+
* *not stable*: does not preserve the ordering of elements that
1923+
compare equal (e.g. "a" and "A" in a sort of letters that
18911924
ignores case).
18921925
* *in-place* in memory.
18931926
* *divide-and-conquer*: sort strategy similar to [`MergeSort`](@ref).
@@ -1903,8 +1936,8 @@ Indicate that a sorting function should use the quick sort
19031936
algorithm, which is *not* stable.
19041937
19051938
Characteristics:
1906-
* *not stable*: does not preserve the ordering of elements which
1907-
compare equal (e.g. "a" and "A" in a sort of letters which
1939+
* *not stable*: does not preserve the ordering of elements that
1940+
compare equal (e.g. "a" and "A" in a sort of letters that
19081941
ignores case).
19091942
* *in-place* in memory.
19101943
* *divide-and-conquer*: sort strategy similar to [`MergeSort`](@ref).
@@ -1922,8 +1955,8 @@ subcollection at each step, until the entire
19221955
collection has been recombined in sorted form.
19231956
19241957
Characteristics:
1925-
* *stable*: preserves the ordering of elements which compare
1926-
equal (e.g. "a" and "A" in a sort of letters which ignores
1958+
* *stable*: preserves the ordering of elements that compare
1959+
equal (e.g. "a" and "A" in a sort of letters that ignores
19271960
case).
19281961
* *not in-place* in memory.
19291962
* *divide-and-conquer* sort strategy.

doc/src/base/base.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ Core.:(===)
126126
Core.isa
127127
Base.isequal
128128
Base.isless
129+
Base.isunordered
129130
Base.ifelse
130131
Core.typeassert
131132
Core.typeof

doc/src/base/sort.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ Base.Sort.defalg(::AbstractArray{<:Union{SmallInlineStrings, Missing}}) = Inline
203203
The default sorting algorithm (returned by `Base.Sort.defalg`) is guaranteed
204204
to be stable since Julia 1.9. Previous versions had unstable edge cases when sorting numeric arrays.
205205

206-
## Alternate orderings
206+
## Alternate Orderings
207207

208208
By default, `sort` and related functions use [`isless`](@ref) to compare two
209209
elements in order to determine which should come first. The

doc/src/manual/missing.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ true
8888
```
8989

9090
The [`isless`](@ref) operator is another exception: `missing` is considered
91-
as greater than any other value. This operator is used by [`sort`](@ref),
91+
as greater than any other value. This operator is used by [`sort!`](@ref),
9292
which therefore places `missing` values after all other values:
9393

9494
```jldoctest

0 commit comments

Comments
 (0)