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
создает отсортированную копию, оставляя его входные данные неизменными. Используйте "громкий" вариант функции сортировки, чтобы изменить существующий массив:
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
перед каждым сравнением, а не один раз для каждого элемента.
Передача lt
, отличного от isless
, вместе с order
, отличным от Base.Order.Forward
или Base.Order.Reverse
, не допускается, в противном случае все параметры независимы и могут использоваться вместе во всех возможных комбинациях. Обратите внимание, что order
также может включать преобразование "by", в этом случае оно применяется после того, что определено с помощью ключевого слова by
. Для получения дополнительной информации о значениях order
смотрите документацию по Альтернативным порядкам.
Отношения между двумя элементами определяются следующим образом (с "меньше" и "больше", обмененными, когда rev=true
):
x
меньшеy
, еслиlt(by(x), by(y))
(илиBase.Order.lt(order, by(x), by(y))
) возвращает true.x
большеy
, еслиy
меньшеx
.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
должны быть эквивалентны.
Например, <
является допустимой функцией lt
для значений Int
, но ≤
не является таковой: она нарушает иррефлексивность. Для значений 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)) # то же самое, что sort(0:3, by=abs(x->x-2))
4-element Vector{Int64}:
2
1
3
0
julia> sort([2, NaN, 1, NaN, 3]) # правильная сортировка с lt по умолчанию = isless
5-element Vector{Float64}:
1.0
2.0
3.0
NaN
NaN
julia> sort([2, NaN, 1, NaN, 3], lt=<) # неправильная сортировка из-за недопустимого lt. Это поведение неопределено.
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)
Сортирует многомерный массив A
вдоль размерности dims
. См. однородную версию 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" в сортировке букв, игнорирующей регистр).
- не на месте в памяти.
- стратегия разделяй и властвуй.
- хорошая производительность для больших коллекций, но обычно не так быстра, как
QuickSort
.
Base.Sort.QuickSort
— ConstantQuickSort
Укажите, что функция сортировки должна использовать алгоритм быстрой сортировки, который не является стабильным.
Характеристики:
- не стабильный: не сохраняет порядок элементов, которые сравниваются как равные (например, "a" и "A" в сортировке букв, игнорирующей регистр).
- на месте в памяти.
- разделяй и властвуй: стратегия сортировки, аналогичная
MergeSort
. - хорошая производительность для больших коллекций.
Base.Sort.PartialQuickSort
— TypePartialQuickSort{T <: Union{Integer,OrdinalRange}}
Укажите, что функция сортировки должна использовать алгоритм частичной быстрой сортировки. PartialQuickSort(k)
похож на QuickSort
, но требуется только найти и отсортировать элементы, которые окажутся в v[k]
, если v
будет полностью отсортирован.
Характеристики:
- неустойчивая: не сохраняет порядок элементов, которые сравниваются как равные (например, "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
должен быть отсортирован в соответствии с порядком, определенным ключевыми словами. Вставка 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
должен быть отсортирован в соответствии с порядком, определенным ключевыми словами. Вставка 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)
Возвращает частичную перестановку I
вектора v
, так что v[I]
возвращает значения полностью отсортированной версии v
по индексу k
. Если 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
, но принимает предвыделенный вектор индексов ix
того же размера, что и v
, который используется для хранения (перестановки) индексов 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
является целым числом, или представление 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!
, экземпляр Ordering
может быть предоставлен с аргументом ключевого слова order
.
Экземпляры Ordering
определяют порядок через функцию Base.Order.lt
, которая работает как обобщение isless
. Поведение этой функции для пользовательских Ordering
должно удовлетворять всем условиям strict weak order. См. sort!
для получения подробной информации и примеров допустимых и недопустимых функций lt
.
Base.Order.Ordering
— TypeBase.Order.Ordering
Абстрактный тип, который представляет строгий слабый порядок на некотором множестве элементов. См. sort!
для получения дополнительной информации.
Используйте Base.Order.lt
, чтобы сравнить два элемента в соответствии с порядком.
Base.Order.lt
— Functionlt(o::Ordering, a, b) -> Bool
Проверьте, меньше ли a
, чем b
, согласно порядку o
.
Base.Order.ord
— Functionord(lt, by, rev::Union{Bool, Nothing}, order::Ordering=Forward)
Создайте объект Ordering
из тех же аргументов, которые используются в sort!
. Элементы сначала преобразуются с помощью функции by
(которая может быть identity
), а затем сравниваются в соответствии с функцией lt
или существующим порядком order
. lt
должен быть isless
или функцией, которая подчиняется тем же правилам, что и параметр lt
функции sort!
. Наконец, полученный порядок будет перевернут, если rev=true
.
Передача lt
, отличного от isless
, вместе с order
, отличным от Base.Order.Forward
или Base.Order.Reverse
, не допускается, в противном случае все параметры независимы и могут использоваться вместе во всех возможных комбинациях.
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
должен подчиняться тем же правилам, что и параметр lt
функции sort!
.
Base.Order.Perm
— TypePerm(order::Ordering, data::AbstractVector)
Ordering
по индексам data
, где i
меньше j
, если data[i]
меньше data[j]
в соответствии с order
. В случае, если data[i]
и data[j]
равны, i
и j
сравниваются по числовому значению.