排序和相关功能
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函数的高性能版本修改现有数组。:
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
排序函数
# '基。排序!`-Function</no-翻译>
sort!(A; dims::Integer, alg::Algorithm=defalg(A), lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward)
在维度"dims"中对多维数组"A"进行排序。 有关可能的命名参数的描述,请参阅一维版本的部分。 '排序!`.
有关排序数组切片的信息,请参阅说明 'sortslices'。
兼容性:Julia1.1
此功能需要至少1.1的Julia版本。 |
例子
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
朱莉娅>排序!(A,dims=2);A
2×2矩阵{Int64}:
1 2
3 4
sort!(A; dims::Integer, alg::Algorithm=defalg(A), lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward)
将多维数组`A`沿着维度`dims’排序。 请参阅 '排序!'用于描述可能的关键字参数。
要对数组的切片进行排序,请参阅 'sortslices'。
兼容性:Julia1.1
此功能至少需要Julia1.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
# '基。排序'-Function
sort(v; alg::Algorithm=defalg(v), lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward)
选项 '排序!',它返回`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`进行排序。 有关可能的命名参数的说明,请参阅说明 '排序!`.
有关排序数组切片的信息,请参阅说明 '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
# '基。sortperm'-Function
sortperm(A; alg::Algorithm=DEFAULT_UNSTABLE, lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward, [dims::Integer])
返回一个置换向量或数组"I",其中元素"A[I]"按排序顺序放置在指定的维度中。 如果’A’有多个维度,则必须指定命名参数`dims'。 使用与以下相同的命名参数设置顺序 '排序!`. 置换保证是稳定的,即使排序算法不稳定:相等元素的索引将按升序排列。
另请参阅说明 'sortperm!`, 'partialsortperm', `invperm'和 '索引'。 有关排序数组切片的信息,请参阅说明 'sortslices'。
兼容性:Julia1.9
接受`dims`的方法需要至少1.9的Julia版本。 |
例子
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
# '基。排序。InsertionSort'—Constant
InsertionSort
使用插入排序算法。
插入排序一次遍历集合的一个元素,将每个元素插入到输出向量中正确排序的位置。
规格说明:
-
稳定性:被认为相等的元素的顺序被保留(例如,当不区分大小写的字母排序时,"a"和"A")。
-
内存中的某个地方执行。
-
要排序的项目数量中的方形production_:非常适合小型集合,但不应用于大型集合。
# '基。排序。QuickSort'—Constant
QuickSort
指定排序函数应使用不稳定的快速排序算法。
规格说明:
-
非稳定性:不保留被认为相等的元素的顺序(例如,在不区分大小写的字母排序时,"a"和"A")。
-
内存中的地方执行。
-
Divide和conquer:类似于的排序策略 'MergeSort'。
-
大集合的良好性能。
# '基。排序。PartialQuickSort'-Type
PartialQuickSort{T <: Union{Integer,OrdinalRange}}
指定排序函数应使用部分快速排序算法。 'PartialQuickSort(k)类似于`QuickSort
,但它只需要搜索和排序元素,如果完全按`v`排序,则会落入`v[k]`。
规格说明:
-
非稳定性:不保留被认为相等的元素的顺序(例如,在不区分大小写的字母排序时,"a"和"A")。
-
内存中的某个地方执行。
-
Divide和conquer:类似于的排序策略 '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
# '基。排序。sortperm!`-Function</no-翻译>
sortperm!(ix, A; alg::Algorithm=DEFAULT_UNSTABLE, lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward, [dims::Integer])
同样地 'sortperm',但接受与`a`具有相同轴的索引`ix`的预分配向量或数组。 'ix`用值`LinearIndices(A)'初始化。
如果任何修改的参数被放置在与任何其他参数相同的内存区域中,则行为可能是意外的。 |
兼容性:Julia1.9
接受`dims`的方法需要至少1.9的Julia版本。 |
例子
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
# '基。sortslices'-Function
sortslices(A; dims, alg::Algorithm=DEFAULT_UNSTABLE, lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward)
对数组`A’的切片进行排序。 强制命名参数’dims’必须是整数或整数元组。 它设置切片排序的维度。
例如,如果`A’是一个矩阵,`dims=1`将对行进行排序,`dims=2’将对列进行排序。 请注意,一维切片中的默认比较函数执行词典排序。
有关其他命名参数的信息,请参阅 '排序!`.
例子
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)`将通过将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
订购相关功能
# '基。issorted'-Function
issorted(v, lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward)
检查集合是否按排序顺序排列。 命名参数更改排序顺序,如以下文档中所述 '排序!`.
例子
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
# *'基。排序。searchsorted'`-Function
searchsorted(v, x; by=identity, lt=isless, rev=false)
返回`v`中的索引范围,其中值等效于`x`,或者如果`v`不包含等效于`x`的值,则返回位于插入点的空范围。 向量’v’必须按照命名参数确定的顺序排序。 有关命名参数的含义和等价的定义,请参阅说明 '排序!`. 请注意,'by’函数应用于’x’的所需值以及`v’中的值。
范围通常通过二进制搜索找到,但对于某些输入数据存在优化的实现。
例子
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
# *'基。排序。searchsortedfirst'`-Function
searchsortedfirst(v, x; by=identity, lt=isless, rev=false)
返回`v`中未在`x’之前排序的第一个值的索引。 如果`v’中的所有值都在`x’之前排序,则返回’lastindex(v)+1'。
向量’v’必须按照命名参数确定的顺序排序。 插入时('插入!)'x’通过返回的索引,排序后的顺序被保留。 有关命名参数的含义和使用方法,请参阅说明 '排序!
. 请注意,'by’函数应用于’x’的所需值以及`v’中的值。
索引通常通过二进制搜索找到,但对于某些输入数据存在优化的实现。
另请参阅说明 '最后搜索', '搜索', '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
朱莉娅>搜索第一([1, 2, 4, 5, 5, 7], 9) # 没有火柴,在最后插入
7
朱莉娅>搜索第一([1, 2, 4, 5, 5, 7], 0) # 没有匹配项,在开头插入
1
julia>searchsortedfirst([1=>"one",2=>"two",4=>"four"],3=>"three",by=first)#比较成对的键
的3
# *'基。排序。searchsortedlast'`-Function
searchsortedlast(v, x; by=identity, lt=isless, rev=false)
返回`v`中最后一个值的索引,它不是在`x’之后排序的。 如果`v’中的所有值都在`x’之后排序,则返回’firstindex(v)-1'。
向量’v’必须按照命名参数确定的顺序排序。 插入时('插入!)'x’紧接着返回的索引,排序后的顺序被保留。 有关使用命名参数的含义和方法,请参阅说明 '排序!
. 请注意,'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
# '基。排序。插入`-Function</no-翻译>
insorted(x, v; by=identity, lt=isless, rev=false) -> Bool
确定向量’v’是否包含与`x’等价的任何值。 向量’v’必须按照命名参数确定的顺序排序。 有关命名参数的含义和等价的定义,请参阅说明 '排序!`. 请注意,'by’函数应用于’x’的所需值以及`v’中的值。
验证通常通过二进制搜索来执行,但是对于某些输入数据存在优化的实现。
另请参阅说明 '在'。
例子
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
兼容性:Julia1.6
在Julia1.6中添加了"被保险人"。 |
# '基。排序。partialsort!`-Function</no-翻译>
partialsort!(v, k; by=identity, lt=isless, rev=false)
对向量`v’进行部分排序,以便索引为`k`的值(或相邻值的范围,如果`k`是一个范围)位于数组完全排序时它将所在的位置。 如果’k’是单个索引,则返回此值。 如果’k’是一个范围,则返回这些索引中的值数组。 注意’partialsort!`不执行输入数组的完整排序。
有关命名参数的信息,请参阅 '排序!`.
例子
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
# '基。排序。partialsort'-Function
partialsort(v, k, by=identity, lt=isless, rev=false)
选项 'partialsort!,它在部分排序之前复制`v,从而返回与’partialsort相同的结果!',但保持’v’不变。
# '基。排序。partialsortperm'-Function
partialsortperm(v, k; by=identity, lt=isless, rev=false)
返回向量`v`的部分置换`I`,因此`v[I]返回索引`k`处`v`的完全排序版本的值。 如果’k’是一个范围,则返回索引向量。 如果’k’是整数,则返回一个索引。 顺序是使用与"排序"相同的命名参数设置的!
. 排列是稳定的:相等元素的索引将按升序排列。
此函数等效于调用'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
# '基。排序。partialsortperm!`-Function</no-翻译>
partialsortperm!(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)
如果’k`是整数,则返回的值是索引向量`ix`的第`k`个元素,如果`k`是范围,则返回`ix`的表示。
如果任何修改的参数被放置在与任何其他参数相同的内存区域中,则行为可能是意外的。 |
例子
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
排序算法
目前,在Julia的基本版本中公开了四种排序算法:
默认情况下,"排序"函数系列使用稳定的排序算法,可以快速处理大多数输入数据。 算法的确切选择是允许在将来改进性能的实现特性。 目前,根据输入数据的类型,大小和组成,使用RadixSort,ScratchQuickSort,InsertionSort和CountingSort的混合。 实施细节可能会发生变化,但它们现在可以在扩展帮助中找到`??基地。DEFAULT_STABLE’和其中指定的内部排序算法的文档字符串。
您可以使用关键字`alg’显式指定首选算法(例如,sort!(v,alg=PartialQuickSort(10:20))
)或通过向`Base添加专门的方法来重新配置自定义类型的默认排序算法。排序。defalg’功能。 例如,https://github.com/JuliaStrings/InlineStrings.jl/blob/v1.3.2/src/InlineStrings.jl#L903[InlineStrings.jl]定义以下方法:
Base.Sort.defalg(::AbstractArray{<:Union{SmallInlineStrings, Missing}}) = InlineStringSort
兼容性:Julia1.9
默认排序算法(由`Base返回。排序。defalg`)从Julia1.9开始保证稳定。 以前的版本在对数值数组进行排序时存在不稳定的边缘情况。 |
备选安排
默认情况下,sort
,`searchsorted’和相关函数使用 `isless'比较两个元素以确定哪一个应该是第一个。 抽象类型 '基地。秩序。Ordering'提供了一种为同一组元素定义替代排序的机制:当调用排序函数时,例如’sort!','Ordering’的实例可以用命名参数`order`来指定。
'Ordering’实例使用函数定义顺序 Base.Order.lt '
,这可以作为`isless’的概括。 具有自定义排序('Ordering')的此函数的操作必须满足所有条件https://en.wikipedia.org/wiki/Weak_ordering#Strict_weak_orderings [严格的弱序]。 请参阅说明 '排序!具有有效和无效`lt’函数的信息和示例。
# '基。秩序。订购'-Type</no-翻译>
Base.Order.Ordering
表示某组元素中严格弱顺序的抽象类型。 有关详细信息,请参阅说明 '排序!`.
要根据顺序比较两个元素,请使用 Base.Order.lt
。
# *'基。秩序。ord'`-Function
ord(lt, by, rev::Union{Bool, Nothing}, order::Ordering=Forward)
创建对象 'Ordering'基于函数使用的相同参数 '排序!. 首先,使用`by`函数转换元素(这可以是 'identity'),然后根据`lt`函数或现有的`order’排序进行比较。 '它’应该是 'isless'或者是遵循与函数的’lt’参数相同规则的函数 '排序!. 最后,如果`rev=true',则最终顺序反转。
转让除"无"以外的"lt"及除"无"以外的"订单"。 '基地。秩序。前进'或 '基地。秩序。反',禁止。 否则,所有参数都是独立的,并且可以在所有可能的组合中一起使用。
# '基。秩序。反向排序'-Type</no-翻译>
ReverseOrdering(fwd::Ordering=Forward)
颠倒顺序的外壳。
对于给定的"O"的"排序",所有的"a"、"b`都是如此:
lt(ReverseOrdering(o), a, b) == lt(o, b, a)
#
<无翻译>*Base.Order.By
*-Type</no-翻译>
By(by, order::Ordering=Forward)
'Ordering',通过`by`函数将`order`应用于元素转换后的元素。
# '基。秩序。烫发`-Type</no-翻译>
Perm(order::Ordering, data::AbstractVector)
根据`order`,如果`data[i]小于`data[j]
,则`i`小于`j`的`data`的索引的’Ordering'。 如果’data[i]`和`data[j]`相等,则通过数值比较`i`和`j'。