Sorting and Related Functions
Julia 拥有一个广泛且灵活的 API,用于对已排序的值数组进行排序和交互。默认情况下,Julia 选择合理的算法并按升序排序:
julia> sort([2,3,1])
3-element Vector{Int64}:
1
2
3
您也可以按相反顺序排序:
julia> sort([2,3,1], rev=true)
3-element Vector{Int64}:
3
2
1
sort
构造一个已排序的副本,保持其输入不变。使用 "bang" 版本的排序函数来改变现有数组:
julia> a = [2,3,1];
julia> sort!(a);
julia> a
3-element Vector{Int64}:
1
2
3
而不是直接对数组进行排序,您可以计算一个数组索引的排列,使数组按排序顺序排列:
julia> v = randn(5)
5-element Array{Float64,1}:
0.297288
0.382396
-0.597634
-0.0104452
-0.839027
julia> p = sortperm(v)
5-element Array{Int64,1}:
5
3
4
1
2
julia> v[p]
5-element Array{Float64,1}:
-0.839027
-0.597634
-0.0104452
0.297288
0.382396
数组可以根据其值的任意变换进行排序:
julia> sort(v, by=abs)
5-element Array{Float64,1}:
-0.0104452
0.297288
0.382396
-0.597634
-0.839027
或通过变换以相反的顺序:
julia> sort(v, by=abs, rev=true)
5-element Array{Float64,1}:
-0.839027
-0.597634
0.382396
0.297288
-0.0104452
如果需要,可以选择排序算法:
julia> sort(v, alg=InsertionSort)
5-element Array{Float64,1}:
-0.839027
-0.597634
-0.0104452
0.297288
0.382396
所有与排序和顺序相关的函数都依赖于一个“少于”关系,定义了一个 strict weak order,用于要操作的值。默认情况下调用 isless
函数,但可以通过 lt
关键字指定关系,该函数接受两个数组元素,并仅在第一个参数“少于”第二个时返回 true
。有关更多信息,请参见 sort!
和 Alternate Orderings。
Sorting Functions
Base.sort!
— Functionsort!(v; alg::Algorithm=defalg(v), lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward)
就地对向量 v
进行排序。默认使用稳定算法:相等元素的顺序得以保留。可以通过 alg
关键字选择特定算法(有关可用算法,请参见 排序算法)。
元素首先通过函数 by
进行转换,然后根据函数 lt
或排序 order
进行比较。最后,如果 rev=true
,则结果顺序会被反转(这保留了前向稳定性:相等的元素不会被反转)。当前实现是在每次比较之前应用 by
转换,而不是每个元素一次。
传递一个与 isless
不同的 lt
以及一个与 Base.Order.Forward
或 Base.Order.Reverse
不同的 order
是不允许的,否则所有选项都是独立的,可以在所有可能的组合中一起使用。请注意,order
也可以包含一个 "by" 转换,在这种情况下,它在 by
关键字定义的转换之后应用。有关 order
值的更多信息,请参见 替代排序 的文档。
两个元素之间的关系定义如下(当 rev=true
时,“小于”和“大于”互换):
- 如果
lt(by(x), by(y))
(或Base.Order.lt(order, by(x), by(y))
)为真,则x
小于y
。 - 如果
y
小于x
,则x
大于y
。 - 如果两者都不小于对方,则
x
和y
是等价的(“不可比较”有时用作“等价”的同义词)。
sort!
的结果是排序的,意味着每个元素都大于或等于前一个元素。
lt
函数必须定义严格的弱序,即它必须是
- 非自反的:
lt(x, x)
始终返回false
, - 不对称的:如果
lt(x, y)
返回true
,则lt(y, x)
返回false
, - 传递的:
lt(x, y) && lt(y, z)
意味着lt(x, z)
, - 在等价中是传递的:
!lt(x, y) && !lt(y, x)
和!lt(y, z) && !lt(z, y)
一起意味着!lt(x, z) && !lt(z, x)
。换句话说:如果x
和y
是等价的,并且y
和z
是等价的,则x
和z
必须是等价的。
例如,<
是 Int
值的有效 lt
函数,但 ≤
不是:它违反了非自反性。对于 Float64
值,即使 <
也是无效的,因为它违反了第四个条件:1.0
和 NaN
是等价的,NaN
和 2.0
也是等价的,但 1.0
和 2.0
不是等价的。
另请参见 sort
、sortperm
、sortslices
、partialsort!
、partialsortperm
、issorted
、searchsorted
、insorted
、Base.Order.ord
。
示例
julia> v = [3, 1, 2]; sort!(v); v
3-element Vector{Int64}:
1
2
3
julia> v = [3, 1, 2]; sort!(v, rev = true); v
3-element Vector{Int64}:
3
2
1
julia> v = [(1, "c"), (3, "a"), (2, "b")]; sort!(v, by = x -> x[1]); v
3-element Vector{Tuple{Int64, String}}:
(1, "c")
(2, "b")
(3, "a")
julia> v = [(1, "c"), (3, "a"), (2, "b")]; sort!(v, by = x -> x[2]); v
3-element Vector{Tuple{Int64, String}}:
(3, "a")
(2, "b")
(1, "c")
julia> sort(0:3, by=x->x-2, order=Base.Order.By(abs)) # same as sort(0:3, by=abs(x->x-2))
4-element Vector{Int64}:
2
1
3
0
julia> sort([2, NaN, 1, NaN, 3]) # correct sort with default lt=isless
5-element Vector{Float64}:
1.0
2.0
3.0
NaN
NaN
julia> sort([2, NaN, 1, NaN, 3], lt=<) # wrong sort due to invalid lt. This behavior is undefined.
5-element Vector{Float64}:
2.0
NaN
1.0
NaN
3.0
sort!(A; dims::Integer, alg::Algorithm=defalg(A), lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward)
沿维度 dims
对多维数组 A
进行排序。有关可能的关键字参数的描述,请参见一维版本的 sort!
。
要对数组的切片进行排序,请参考 sortslices
。
此函数至少需要 Julia 1.1。
示例
julia> A = [4 3; 1 2]
2×2 Matrix{Int64}:
4 3
1 2
julia> sort!(A, dims = 1); A
2×2 Matrix{Int64}:
1 2
4 3
julia> sort!(A, dims = 2); A
2×2 Matrix{Int64}:
1 2
3 4
Base.sort
— Functionsort(v; alg::Algorithm=defalg(v), lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward)
sort!
的变体,返回 v
的排序副本,而不修改 v
本身。
示例
julia> v = [3, 1, 2];
julia> sort(v)
3-element Vector{Int64}:
1
2
3
julia> v
3-element Vector{Int64}:
3
1
2
sort(A; dims::Integer, alg::Algorithm=defalg(A), lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward)
沿给定维度对多维数组 A
进行排序。有关可能的关键字参数的描述,请参见 sort!
。
要对数组的切片进行排序,请参考 sortslices
。
示例
julia> A = [4 3; 1 2]
2×2 Matrix{Int64}:
4 3
1 2
julia> sort(A, dims = 1)
2×2 Matrix{Int64}:
1 2
4 3
julia> sort(A, dims = 2)
2×2 Matrix{Int64}:
3 4
1 2
Base.sortperm
— Functionsortperm(A; alg::Algorithm=DEFAULT_UNSTABLE, lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward, [dims::Integer])
返回一个排列向量或数组 I
,使得 A[I]
在给定维度上按排序顺序排列。如果 A
有多个维度,则必须指定 dims
关键字参数。排序顺序使用与 sort!
相同的关键字指定。即使排序算法是不稳定的,排列也保证是稳定的:相等元素的索引将按升序出现。
另请参见 sortperm!
、partialsortperm
、invperm
、indexin
。要对数组的切片进行排序,请参阅 sortslices
。
接受 dims
的方法至少需要 Julia 1.9。
示例
julia> v = [3, 1, 2];
julia> p = sortperm(v)
3-element Vector{Int64}:
2
3
1
julia> v[p]
3-element Vector{Int64}:
1
2
3
julia> A = [8 7; 5 6]
2×2 Matrix{Int64}:
8 7
5 6
julia> sortperm(A, dims = 1)
2×2 Matrix{Int64}:
2 4
1 3
julia> sortperm(A, dims = 2)
2×2 Matrix{Int64}:
3 1
2 4
Base.Sort.InsertionSort
— Constant插入排序
使用插入排序算法。
插入排序一次遍历集合中的一个元素,将每个元素插入到输出向量的正确排序位置。
特点:
- 稳定性:保留比较相等的元素的顺序
(例如,在忽略大小写的字母排序中,“a”和“A”)。
- 原地 在内存中。
- 平方性能 在要排序的元素数量上:
它非常适合小集合,但不应用于大集合。
Base.Sort.MergeSort
— Constant归并排序
指示排序函数应使用归并排序算法。归并排序将集合分成子集合,并反复合并它们,在每一步中对每个子集合进行排序,直到整个集合以排序的形式重新组合。
特点:
- 稳定性:保留比较相等的元素的顺序(例如,在忽略大小写的字母排序中,“a”和“A”)。
- 不在内存中就地。
- 分治排序策略。
- 对大集合性能良好,但通常不如
快速排序
快。
Base.Sort.QuickSort
— Constant快速排序
指示排序函数应使用快速排序算法,该算法是不稳定的。
特点:
- 不稳定:不保留比较相等的元素的顺序(例如,在忽略大小写的字母排序中,“a”和“A”)。
- 原地在内存中。
- 分治法:排序策略类似于
MergeSort
。 - 对大集合有良好的性能。
Base.Sort.PartialQuickSort
— TypePartialQuickSort{T <: Union{Integer,OrdinalRange}}
表示一个排序函数应该使用部分快速排序算法。PartialQuickSort(k)
类似于 QuickSort
,但只需要找到并排序那些在 v
完全排序时会出现在 v[k]
中的元素。
特点:
- 不稳定:不保留比较相等的元素的顺序(例如,在忽略大小写的字母排序中,“a”和“A”)。
- 原地 在内存中。
- 分治法:排序策略类似于
MergeSort
。
请注意,PartialQuickSort(k)
不一定会对整个数组进行排序。例如,
julia> x = rand(100);
julia> k = 50:100;
julia> s1 = sort(x; alg=QuickSort);
julia> s2 = sort(x; alg=PartialQuickSort(k));
julia> map(issorted, (s1, s2))
(true, false)
julia> map(x->issorted(x[k]), (s1, s2))
(true, true)
julia> s1[k] == s2[k]
true
Base.Sort.sortperm!
— Functionsortperm!(ix, A; alg::Algorithm=DEFAULT_UNSTABLE, lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward, [dims::Integer])
与 sortperm
类似,但接受一个预分配的索引向量或数组 ix
,其 axes
与 A
相同。ix
被初始化为包含 LinearIndices(A)
的值。
当任何被修改的参数与其他参数共享内存时,行为可能会出乎意料。
接受 dims
的方法需要至少 Julia 1.9。
示例
julia> v = [3, 1, 2]; p = zeros(Int, 3);
julia> sortperm!(p, v); p
3-element Vector{Int64}:
2
3
1
julia> v[p]
3-element Vector{Int64}:
1
2
3
julia> A = [8 7; 5 6]; p = zeros(Int,2, 2);
julia> sortperm!(p, A; dims=1); p
2×2 Matrix{Int64}:
2 4
1 3
julia> sortperm!(p, A; dims=2); p
2×2 Matrix{Int64}:
3 1
2 4
Base.sortslices
— Functionsortslices(A; dims, alg::Algorithm=DEFAULT_UNSTABLE, lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward)
对数组 A
的切片进行排序。必需的关键字参数 dims
必须是一个整数或整数元组。它指定了切片排序的维度。
例如,如果 A
是一个矩阵,dims=1
将排序行,dims=2
将排序列。请注意,默认的比较函数在一维切片上是按字典序排序的。
有关其余关键字参数,请参见 sort!
的文档。
示例
julia> sortslices([7 3 5; -1 6 4; 9 -2 8], dims=1) # 排序行
3×3 Matrix{Int64}:
-1 6 4
7 3 5
9 -2 8
julia> sortslices([7 3 5; -1 6 4; 9 -2 8], dims=1, lt=(x,y)->isless(x[2],y[2]))
3×3 Matrix{Int64}:
9 -2 8
7 3 5
-1 6 4
julia> sortslices([7 3 5; -1 6 4; 9 -2 8], dims=1, rev=true)
3×3 Matrix{Int64}:
9 -2 8
7 3 5
-1 6 4
julia> sortslices([7 3 5; 6 -1 -4; 9 -2 8], dims=2) # 排序列
3×3 Matrix{Int64}:
3 5 7
-1 -4 6
-2 8 9
julia> sortslices([7 3 5; 6 -1 -4; 9 -2 8], dims=2, alg=InsertionSort, lt=(x,y)->isless(x[2],y[2]))
3×3 Matrix{Int64}:
5 3 7
-4 -1 6
8 -2 9
julia> sortslices([7 3 5; 6 -1 -4; 9 -2 8], dims=2, rev=true)
3×3 Matrix{Int64}:
7 5 3
6 -4 -1
9 8 -2
更高维度
sortslices
自然扩展到更高维度。例如,如果 A
是一个 2x2x2 的数组,sortslices(A, dims=3)
将在第 3 维度内排序切片,将 2x2 的切片 A[:, :, 1]
和 A[:, :, 2]
传递给比较函数。请注意,虽然在高维切片上没有默认顺序,但您可以使用 by
或 lt
关键字参数来指定这样的顺序。
如果 dims
是一个元组,则 dims
中维度的顺序是相关的,并指定切片的线性顺序。例如,如果 A
是三维的,dims
是 (1, 2)
,则前两个维度的顺序被重新排列,以便对剩余的第三维度的切片进行排序。如果 dims
是 (2, 1)
,则将取相同的切片,但结果顺序将是行优先的。
更高维度示例
julia> A = [4 3; 2 1 ;;; 'A' 'B'; 'C' 'D']
2×2×2 Array{Any, 3}:
[:, :, 1] =
4 3
2 1
[:, :, 2] =
'A' 'B'
'C' 'D'
julia> sortslices(A, dims=(1,2))
2×2×2 Array{Any, 3}:
[:, :, 1] =
1 3
2 4
[:, :, 2] =
'D' 'B'
'C' 'A'
julia> sortslices(A, dims=(2,1))
2×2×2 Array{Any, 3}:
[:, :, 1] =
1 2
3 4
[:, :, 2] =
'D' 'C'
'B' 'A'
julia> sortslices(reshape([5; 4; 3; 2; 1], (1,1,5)), dims=3, by=x->x[1,1])
1×1×5 Array{Int64, 3}:
[:, :, 1] =
1
[:, :, 2] =
2
[:, :, 3] =
3
[:, :, 4] =
4
[:, :, 5] =
5
Order-Related Functions
Base.issorted
— Functionissorted(v, lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward)
测试一个集合是否按排序顺序排列。关键字修改被视为已排序的顺序,如 sort!
文档中所述。
示例
julia> issorted([1, 2, 3])
true
julia> issorted([(1, "b"), (2, "a")], by = x -> x[1])
true
julia> issorted([(1, "b"), (2, "a")], by = x -> x[2])
false
julia> issorted([(1, "b"), (2, "a")], by = x -> x[2], rev=true)
true
julia> issorted([1, 2, -2, 3], by=abs)
true
Base.Sort.searchsorted
— Functionsearchsorted(v, x; by=identity, lt=isless, rev=false)
返回在 v
中与 x
等值的索引范围,如果 v
不包含与 x
等值的元素,则返回位于插入点的空范围。向量 v
必须根据关键字定义的顺序进行排序。有关关键字的含义和等值的定义,请参阅 sort!
。请注意,by
函数应用于被搜索的值 x
以及 v
中的值。
该范围通常使用二分搜索找到,但对于某些输入有优化的实现。
另请参见:searchsortedfirst
,sort!
,insorted
,findall
。
示例
julia> searchsorted([1, 2, 4, 5, 5, 7], 4) # 单个匹配
3:3
julia> searchsorted([1, 2, 4, 5, 5, 7], 5) # 多个匹配
4:5
julia> searchsorted([1, 2, 4, 5, 5, 7], 3) # 无匹配,在中间插入
3:2
julia> searchsorted([1, 2, 4, 5, 5, 7], 9) # 无匹配,在末尾插入
7:6
julia> searchsorted([1, 2, 4, 5, 5, 7], 0) # 无匹配,在开头插入
1:0
julia> searchsorted([1=>"one", 2=>"two", 2=>"two", 4=>"four"], 2=>"two", by=first) # 比较对的键
2:3
Base.Sort.searchsortedfirst
— Functionsearchsortedfirst(v, x; by=identity, lt=isless, rev=false)
返回 v
中第一个不在 x
之前的值的索引。如果 v
中的所有值都在 x
之前,则返回 lastindex(v) + 1
。
向量 v
必须根据关键字定义的顺序进行排序。在返回的索引处使用 insert!
插入 x
将保持排序顺序。有关关键字的含义和使用,请参阅 sort!
。请注意,by
函数应用于被搜索的值 x
以及 v
中的值。
索引通常使用二分搜索找到,但对于某些输入有优化的实现。
另请参见: searchsortedlast
, searchsorted
, findfirst
.
示例
julia> searchsortedfirst([1, 2, 4, 5, 5, 7], 4) # 单个匹配
3
julia> searchsortedfirst([1, 2, 4, 5, 5, 7], 5) # 多个匹配
4
julia> searchsortedfirst([1, 2, 4, 5, 5, 7], 3) # 无匹配,在中间插入
3
julia> searchsortedfirst([1, 2, 4, 5, 5, 7], 9) # 无匹配,在末尾插入
7
julia> searchsortedfirst([1, 2, 4, 5, 5, 7], 0) # 无匹配,在开始插入
1
julia> searchsortedfirst([1=>"one", 2=>"two", 4=>"four"], 3=>"three", by=first) # 比较对的键
3
Base.Sort.searchsortedlast
— Functionsearchsortedlast(v, x; by=identity, lt=isless, rev=false)
返回 v
中最后一个不在 x
之后的值的索引。如果 v
中的所有值都在 x
之后,则返回 firstindex(v) - 1
。
向量 v
必须根据关键字定义的顺序进行排序。在返回的索引后立即 insert!
x
将保持排序顺序。有关关键字的含义和使用,请参阅 sort!
。请注意,by
函数应用于被搜索的值 x
以及 v
中的值。
索引通常使用二分搜索找到,但对于某些输入有优化的实现。
示例
julia> searchsortedlast([1, 2, 4, 5, 5, 7], 4) # 单个匹配
3
julia> searchsortedlast([1, 2, 4, 5, 5, 7], 5) # 多个匹配
5
julia> searchsortedlast([1, 2, 4, 5, 5, 7], 3) # 无匹配,在中间插入
2
julia> searchsortedlast([1, 2, 4, 5, 5, 7], 9) # 无匹配,在末尾插入
6
julia> searchsortedlast([1, 2, 4, 5, 5, 7], 0) # 无匹配,在开始插入
0
julia> searchsortedlast([1=>"one", 2=>"two", 4=>"four"], 3=>"three", by=first) # 比较对的键
2
Base.Sort.insorted
— Functioninsorted(x, v; by=identity, lt=isless, rev=false) -> Bool
确定向量 v
是否包含与 x
等价的任何值。向量 v
必须根据关键字定义的顺序进行排序。有关关键字的含义和等价的定义,请参阅 sort!
。请注意,by
函数应用于被搜索的值 x
以及 v
中的值。
检查通常使用二分搜索进行,但对于某些输入有优化的实现。
另请参见 in
。
示例
julia> insorted(4, [1, 2, 4, 5, 5, 7]) # 单个匹配
true
julia> insorted(5, [1, 2, 4, 5, 5, 7]) # 多个匹配
true
julia> insorted(3, [1, 2, 4, 5, 5, 7]) # 无匹配
false
julia> insorted(9, [1, 2, 4, 5, 5, 7]) # 无匹配
false
julia> insorted(0, [1, 2, 4, 5, 5, 7]) # 无匹配
false
julia> insorted(2=>"TWO", [1=>"one", 2=>"two", 4=>"four"], by=first) # 比较对的键
true
insorted
在 Julia 1.6 中添加。
Base.Sort.partialsort!
— Functionpartialsort!(v, k; by=identity, lt=isless, rev=false)
部分地对向量 v
进行就地排序,使得索引 k
处的值(如果 k
是一个范围,则为相邻值的范围)出现在如果数组完全排序时应该出现的位置。如果 k
是单个索引,则返回该值;如果 k
是一个范围,则返回这些索引处的值的数组。请注意,partialsort!
可能不会完全排序输入数组。
有关关键字参数,请参见 sort!
的文档。
示例
julia> a = [1, 2, 4, 3, 4]
5-element Vector{Int64}:
1
2
4
3
4
julia> partialsort!(a, 4)
4
julia> a
5-element Vector{Int64}:
1
2
3
4
4
julia> a = [1, 2, 4, 3, 4]
5-element Vector{Int64}:
1
2
4
3
4
julia> partialsort!(a, 4, rev=true)
2
julia> a
5-element Vector{Int64}:
4
4
3
2
1
Base.Sort.partialsort
— Functionpartialsort(v, k, by=identity, lt=isless, rev=false)
partialsort!
的变体,它在部分排序之前复制 v
,因此返回与 partialsort!
相同的结果,但不修改 v
。
Base.Sort.partialsortperm
— Functionpartialsortperm(v, k; by=identity, lt=isless, rev=false)
返回向量 v
的部分排列 I
,使得 v[I]
在索引 k
处返回 v
的完全排序版本的值。如果 k
是一个范围,则返回一个索引向量;如果 k
是一个整数,则返回一个单一索引。顺序使用与 sort!
相同的关键字指定。该排列是稳定的:相等元素的索引将按升序出现。
此函数等效于但比调用 sortperm(...)[k]
更高效。
示例
julia> v = [3, 1, 2, 1];
julia> v[partialsortperm(v, 1)]
1
julia> p = partialsortperm(v, 1:3)
3-element view(::Vector{Int64}, 1:3) with eltype Int64:
2
4
3
julia> v[p]
3-element Vector{Int64}:
1
1
2
Base.Sort.partialsortperm!
— Functionpartialsortperm!(ix, v, k; by=identity, lt=isless, rev=false)
类似于 partialsortperm
,但接受一个与 v
大小相同的预分配索引向量 ix
,该向量用于存储 v
的索引(的一个排列)。
ix
被初始化为包含 v
的索引。
(通常,v
的索引将是 1:length(v)
,尽管如果 v
具有非一基索引的替代数组类型,例如 OffsetArray
,则 ix
必须共享这些相同的索引)
返回时,ix
保证在其排序位置中具有索引 k
,使得
partialsortperm!(ix, v, k);
v[ix[k]] == partialsort(v, k)
返回值是 ix
的第 k
个元素,如果 k
是一个整数,或者是 ix
的视图,如果 k
是一个范围。
当任何被修改的参数与其他参数共享内存时,行为可能会出乎意料。
示例
julia> v = [3, 1, 2, 1];
julia> ix = Vector{Int}(undef, 4);
julia> partialsortperm!(ix, v, 1)
2
julia> ix = [1:4;];
julia> partialsortperm!(ix, v, 2:3)
2-element view(::Vector{Int64}, 2:3) with eltype Int64:
4
3
```
Sorting Algorithms
目前在基础 Julia 中公开可用的四种排序算法:
默认情况下,sort
函数族使用在大多数输入上都很快的稳定排序算法。确切的算法选择是一个实现细节,以便于未来的性能改进。目前,根据输入类型、大小和组成,使用 RadixSort
、ScratchQuickSort
、InsertionSort
和 CountingSort
的混合体。实现细节可能会发生变化,但目前可以在 ??Base.DEFAULT_STABLE
的扩展帮助和那里列出的内部排序算法的文档字符串中找到。
您可以通过 alg
关键字明确指定您首选的算法(例如 sort!(v, alg=PartialQuickSort(10:20))
),或者通过向 Base.Sort.defalg
函数添加专门的方法来重新配置自定义类型的默认排序算法。例如,InlineStrings.jl 定义了以下方法:
Base.Sort.defalg(::AbstractArray{<:Union{SmallInlineStrings, Missing}}) = InlineStringSort
默认的排序算法(由 Base.Sort.defalg
返回)自 Julia 1.9 起保证是稳定的。之前的版本在排序数字数组时存在不稳定的边缘情况。
Alternate Orderings
默认情况下,sort
、searchsorted
和相关函数使用 isless
来比较两个元素,以确定哪个应该先出现。Base.Order.Ordering
抽象类型提供了一种机制,用于在同一组元素上定义替代排序:在调用像 sort!
这样的排序函数时,可以通过关键字参数 order
提供一个 Ordering
的实例。
Ordering
的实例通过 Base.Order.lt
函数定义了一个顺序,该函数作为 isless
的一种推广。此函数在自定义 Ordering
上的行为必须满足 strict weak order 的所有条件。有关有效和无效 lt
函数的详细信息和示例,请参见 sort!
。
Base.Order.Ordering
— TypeBase.Order.lt
— Functionlt(o::Ordering, a, b) -> Bool
测试 a
是否小于 b
,根据排序 o
。
Base.Order.ord
— Functionord(lt, by, rev::Union{Bool, Nothing}, order::Ordering=Forward)
从与sort!
使用的相同参数构造一个Ordering
对象。元素首先通过函数by
(可以是identity
)进行转换,然后根据函数lt
或现有的排序order
进行比较。lt
应该是isless
或遵循与sort!
的lt
参数相同规则的函数。最后,如果rev=true
,则结果顺序会被反转。
传递一个与isless
不同的lt
以及一个与Base.Order.Forward
或Base.Order.Reverse
不同的order
是不允许的,否则所有选项都是独立的,可以在所有可能的组合中一起使用。
Base.Order.Forward
— ConstantBase.Order.Forward
默认排序根据 isless
进行。
Base.Order.ReverseOrdering
— TypeReverseOrdering(fwd::Ordering=Forward)
一个反转排序的包装器。
对于给定的 Ordering
o
,以下对于所有 a
,b
成立:
lt(ReverseOrdering(o), a, b) == lt(o, b, a)
Base.Order.Reverse
— ConstantBase.Order.Reverse
根据 isless
进行反向排序。
Base.Order.By
— TypeBy(by, order::Ordering=Forward)
Ordering
将 order
应用到经过函数 by
转换后的元素。
Base.Order.Lt
— TypeLt(lt)
Ordering
调用 lt(a, b)
来比较元素。lt
必须遵循与 sort!
的 lt
参数相同的规则。
Base.Order.Perm
— TypePerm(order::Ordering, data::AbstractVector)
Ordering
在 data
的索引上,其中如果 data[i]
根据 order
小于 data[j]
,则 i
小于 j
。如果 data[i]
和 data[j]
相等,则通过数值比较 i
和 j
。