diff --git a/NEWS.md b/NEWS.md index 2068723966512..352ec6dc8ef0c 100644 --- a/NEWS.md +++ b/NEWS.md @@ -25,6 +25,8 @@ New library functions New library features -------------------- +`sort(keys(::Dict))` and `sort(values(::Dict))` now automatically collect, they previously threw ([#56978]). + Standard library changes ------------------------ diff --git a/base/sort.jl b/base/sort.jl index 8254f56b3f952..8196601f3757f 100644 --- a/base/sort.jl +++ b/base/sort.jl @@ -1620,7 +1620,7 @@ defalg(v::AbstractArray) = DEFAULT_STABLE defalg(v::AbstractArray{<:Union{Number, Missing}}) = DEFAULT_UNSTABLE defalg(v::AbstractArray{Missing}) = DEFAULT_UNSTABLE # for method disambiguation defalg(v::AbstractArray{Union{}}) = DEFAULT_UNSTABLE # for method disambiguation -defalg(v::NTuple) = DEFAULT_STABLE +defalg(v) = DEFAULT_STABLE """ sort!(v; alg::Base.Sort.Algorithm=Base.Sort.defalg(v), lt=isless, by=identity, rev::Bool=false, order::Base.Order.Ordering=Base.Order.Forward) @@ -1739,13 +1739,20 @@ function sort!(v::AbstractVector{T}; end """ - sort(v::Union{AbstractVector, NTuple}; alg::Base.Sort.Algorithm=Base.Sort.defalg(v), lt=isless, by=identity, rev::Bool=false, order::Base.Order.Ordering=Base.Order.Forward) + sort(v; alg::Base.Sort.Algorithm=Base.Sort.defalg(v), lt=isless, by=identity, rev::Bool=false, order::Base.Order.Ordering=Base.Order.Forward) + sort(v::NTuple; kws...)::NTuple Variant of [`sort!`](@ref) that returns a sorted copy of `v` leaving `v` itself unmodified. +When calling `sort` on the [`keys`](@ref) or [`values](@ref) of a dictionary, `v` is +collected and then sorted in place. + !!! compat "Julia 1.12" Sorting `NTuple`s requires Julia 1.12 or later. +!!! compat "Julia 1.13" + Sorting keys sets and values iterators requires Julia 1.13 or later. + # Examples ```jldoctest julia> v = [3, 1, 2]; @@ -1761,10 +1768,18 @@ julia> v 3 1 2 + +julia> sort(values(Dict('a'=>2, 'b'=>1))) +2-element Vector{Int64}: + 1 + 2 ``` """ sort(v::AbstractVector; kws...) = sort!(copymutable(v); kws...) +const COLLECT_ON_SORT_TYPES = Union{Base.KeySet, Base.ValueIterator} +sort(v::COLLECT_ON_SORT_TYPES; kws...) = sort!(collect(v); kws...) + function sort(x::NTuple; alg::Algorithm=defalg(x), lt=isless, diff --git a/test/sorting.jl b/test/sorting.jl index e16b30de5bfc8..ab4250fef411b 100644 --- a/test/sorting.jl +++ b/test/sorting.jl @@ -110,6 +110,14 @@ end @test Base.infer_return_type(sort, Tuple{Tuple{Vararg{Int}}}) == Tuple{Vararg{Int}} end +@testset "KeySet and ValueIterator" begin + x = Dict(rand() => randstring() for _ in 1:10) + x0 = deepcopy(x) + @test issorted(sort(keys(x))::Vector{Float64}) + @test issorted(sort(values(x))::Vector{String}) + @test x == x0 +end + @testset "partialsort" begin @test partialsort([3,6,30,1,9],3) == 6 @test partialsort([3,6,30,1,9],3:4) == [6,9]