Engee 文档

排序和相关功能

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

所有与排序和排序相关的功能都基于"小于"比率,该比率定义https://en.wikipedia.org/wiki/Weak_ordering#Strict_weak_orderings 处理值的[严格弱顺序]。 默认情况下调用`isless’函数,但可以使用关键字`lt`指定关系。 这是一个函数,它接受两个数组元素,当且仅当第一个参数"小于"第二个参数时,才返回"true"。 有关详细信息,请参阅说明 '排序!`而在节 备选安排

排序函数

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
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(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

使用插入排序算法。

插入排序一次遍历集合的一个元素,将每个元素插入到输出向量中正确排序的位置。

规格说明:

  • 稳定性:被认为相等的元素的顺序被保留(例如,当不区分大小写的字母排序时,"a"和"A")。

  • 内存中的某个地方执行。

  • 要排序的项目数量中的方形production_:非常适合小型集合,但不应用于大型集合。

MergeSort

指定排序函数应使用合并排序算法。 归并排序将集合划分为子集合并反复合并,在每个阶段对每个子集进行排序,直到将整个集合重新组合为已排序的视图。

规格说明:

  • 稳定性:被认为相等的元素的顺序被保留(例如,当不区分大小写的字母排序时,"a"和"A")。

  • 执行在内存中不合适。

  • 排序策略_"分而治之"_.

  • 对于大型集合,性能良好,但通常不如 '流沙'

QuickSort

指定排序函数应使用不稳定的快速排序算法。

规格说明:

  • 非稳定性:不保留被认为相等的元素的顺序(例如,在不区分大小写的字母排序时,"a"和"A")。

  • 内存中的地方执行。

  • Divide和conquer:类似于的排序策略 'MergeSort'

  • 大集合的良好性能。

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!(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(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(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(v, x; by=identity, lt=isless, rev=false)

返回`v`中的索引范围,其中值等效于`x`,或者如果`v`不包含等效于`x`的值,则返回位于插入点的空范围。 向量’v’必须按照命名参数确定的顺序排序。 有关命名参数的含义和等价的定义,请参阅说明 '排序!`. 请注意,'by’函数应用于’x’的所需值以及`v’中的值。

范围通常通过二进制搜索找到,但对于某些输入数据存在优化的实现。

另请参阅说明 '搜索第一', '排序!, '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
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(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
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!(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(v, k, by=identity, lt=isless, rev=false)

选项 'partialsort!,它在部分排序之前复制`v,从而返回与’partialsort相同的结果!',但保持’v’不变。

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!(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’函数的信息和示例。

Base.Order.Ordering

表示某组元素中严格弱顺序的抽象类型。 有关详细信息,请参阅说明 '排序!`.

要根据顺序比较两个元素,请使用 Base.Order.lt

lt(o::Ordering, a, b) -> Bool

根据`o`的排序检查`a`是否小于`b'。

ord(lt, by, rev::Union{Bool, Nothing}, order::Ordering=Forward)

创建对象 'Ordering'基于函数使用的相同参数 '排序!. 首先,使用`by`函数转换元素(这可以是 'identity'),然后根据`lt`函数或现有的`order’排序进行比较。 '它’应该是 'isless'或者是遵循与函数的’lt’参数相同规则的函数 '排序!. 最后,如果`rev=true',则最终顺序反转。

转让除"无"以外的"lt"及除"无"以外的"订单"。 '基地。秩序。前进''基地。秩序。反',禁止。 否则,所有参数都是独立的,并且可以在所有可能的组合中一起使用。

Base.Order.Forward

默认顺序是根据 'isless`

ReverseOrdering(fwd::Ordering=Forward)

颠倒顺序的外壳。

对于给定的"O"的"排序",所有的"a"、"b`都是如此:

lt(ReverseOrdering(o), a, b) == lt(o, b, a)
Base.Order.Reverse

根据以下情况反转顺序 'isless`

By(by, order::Ordering=Forward)

'Ordering',通过`by`函数将`order`应用于元素转换后的元素。

Lt(lt)

'Ordering`,它调用`lt(a,b)'来比较项目。 'Lt’必须遵循与函数的`lt’参数相同的规则。 '排序!`.

Perm(order::Ordering, data::AbstractVector)

根据`order`,如果`data[i]小于`data[j],则`i`小于`j`的`data`的索引的’Ordering'。 如果’data[i]`和`data[j]`相等,则通过数值比较`i`和`j'。