From 35881021e04edb50b3b69916048066c090460680 Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Mon, 31 Jul 2017 15:55:17 +0200 Subject: [PATCH 1/3] Rename select* functions to partialsort* The new name is more explicit, more consistent with sort and with one of the most commonly used names for this operation (from the C++ stdlib). It also does not conflict with other meanings e.g. for POSIX sockets and SQL. --- NEWS.md | 3 +++ base/deprecated.jl | 6 +++++ base/exports.jl | 8 +++--- base/sort.jl | 59 +++++++++++++++++++++--------------------- base/statistics.jl | 4 +-- doc/src/stdlib/sort.md | 8 +++--- test/core.jl | 6 ++--- test/ranges.jl | 2 +- test/sorting.jl | 24 ++++++++--------- 9 files changed, 65 insertions(+), 55 deletions(-) diff --git a/NEWS.md b/NEWS.md index bbd4f44b6517e..dea80b24dcfaa 100644 --- a/NEWS.md +++ b/NEWS.md @@ -368,6 +368,9 @@ Deprecated or removed respectively. Similarly, `MPFR.get_version()`, has been renamed to `MPFR.version()` ([#23323]). Also, `LinAlg.LAPACK.laver()` has been renamed to `LinAlg.LAPACK.version()` and now returns a `VersionNumber`. + * `select`, `select!`, `selectperm` and `selectperm!` have been renamed respectively to + `partialsort`, `partialsort!`, `partialsortperm` and `partialsortperm!` ([#23051]). + Command-line option changes --------------------------- diff --git a/base/deprecated.jl b/base/deprecated.jl index 34403afcd8121..238fab1ae71b8 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -1742,6 +1742,12 @@ end @deprecate IOContext(io::IO, key, value) IOContext(io, key=>value) +# issue #22791 +@deprecate_binding select partialsort +@deprecate_binding select! partialsort! +@deprecate_binding selectperm partialsortperm +@deprecate_binding selectperm! partialsortperm! + # END 0.7 deprecations # BEGIN 1.0 deprecations diff --git a/base/exports.jl b/base/exports.jl index 4563ccdefb455..10133316bbe6d 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -492,6 +492,10 @@ export ones, parent, parentindexes, + partialsort, + partialsort!, + partialsortperm, + partialsortperm!, permute, permute!, permutedims, @@ -517,8 +521,6 @@ export searchsorted, searchsortedfirst, searchsortedlast, - select!, - select, shuffle, shuffle!, size, @@ -526,8 +528,6 @@ export sort!, sort, sortcols, - selectperm, - selectperm!, sortperm, sortperm!, sortrows, diff --git a/base/sort.jl b/base/sort.jl index 090a2f880a957..7930f856f2f92 100644 --- a/base/sort.jl +++ b/base/sort.jl @@ -15,18 +15,18 @@ import export # also exported by Base # order-only: issorted, - select, - select!, searchsorted, searchsortedfirst, searchsortedlast, # order & algorithm: sort, sort!, - selectperm, - selectperm!, sortperm, sortperm!, + partialsort, + partialsort!, + partialsortperm, + partialsortperm!, sortrows, sortcols, # algorithms: @@ -82,20 +82,20 @@ issorted(itr; lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward) = issorted(itr, ord(lt,by,rev,order)) -function select!(v::AbstractVector, k::Union{Int,OrdinalRange}, o::Ordering) +function partialsort!(v::AbstractVector, k::Union{Int,OrdinalRange}, o::Ordering) inds = indices(v, 1) sort!(v, first(inds), last(inds), PartialQuickSort(k), o) v[k] end """ - select!(v, k, [by=,] [lt=,] [rev=false]) + partialsort!(v, k, [by=,] [lt=,] [rev=false]) Partially sort the vector `v` in place, according to the order specified by `by`, `lt` and `rev` so that the value at index `k` (or range of adjacent values if `k` is a range) occurs at the position where it would appear if the array were fully sorted via a non-stable algorithm. If `k` is a single index, that value is returned; if `k` is a range, an array of -values at those indices is returned. Note that `select!` does not fully sort the input +values at those indices is returned. Note that `partialsort!` does not fully sort the input array. # Examples @@ -108,7 +108,7 @@ julia> a = [1, 2, 4, 3, 4] 3 4 -julia> select!(a, 4) +julia> partialsort!(a, 4) 4 julia> a @@ -127,7 +127,7 @@ julia> a = [1, 2, 4, 3, 4] 3 4 -julia> select!(a, 4, rev=true) +julia> partialsort!(a, 4, rev=true) 2 julia> a @@ -139,17 +139,18 @@ julia> a 1 ``` """ -select!(v::AbstractVector, k::Union{Int,OrdinalRange}; - lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward) = - select!(v, k, ord(lt,by,rev,order)) +partialsort!(v::AbstractVector, k::Union{Int,OrdinalRange}; + lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward) = + partialsort!(v, k, ord(lt,by,rev,order)) """ - select(v, k, [by=,] [lt=,] [rev=false]) + partialsort(v, k, [by=,] [lt=,] [rev=false]) -Variant of [`select!`](@ref) which copies `v` before partially sorting it, thereby returning the -same thing as `select!` but leaving `v` unmodified. +Variant of [`partialsort!`](@ref) which copies `v` before partially sorting it, thereby returning the +same thing as `partialsort!` but leaving `v` unmodified. """ -select(v::AbstractVector, k::Union{Int,OrdinalRange}; kws...) = select!(copymutable(v), k; kws...) +partialsort(v::AbstractVector, k::Union{Int,OrdinalRange}; kws...) = + partialsort!(copymutable(v), k; kws...) # reference on sorted binary search: @@ -667,10 +668,10 @@ julia> v """ sort(v::AbstractVector; kws...) = sort!(copymutable(v); kws...) -## selectperm: the permutation to sort the first k elements of an array ## +## partialsortperm: the permutation to sort the first k elements of an array ## """ - selectperm(v, k, [alg=,] [by=,] [lt=,] [rev=false]) + partialsortperm(v, k, [alg=,] [by=,] [lt=,] [rev=false]) Return a partial permutation of the vector `v`, according to the order specified by `by`, `lt` and `rev`, so that `v[output]` returns the first `k` (or range of adjacent values @@ -681,22 +682,22 @@ from [`select`](@ref) in that it returns a vector of `k` elements instead of jus element. Also note that this is equivalent to, but more efficient than, calling `sortperm(...)[k]`. """ -selectperm(v::AbstractVector, k::Union{Integer,OrdinalRange}; kwargs...) = - selectperm!(similar(Vector{eltype(k)}, indices(v,1)), v, k; kwargs..., initialized=false) +partialsortperm(v::AbstractVector, k::Union{Integer,OrdinalRange}; kwargs...) = + partialsortperm!(similar(Vector{eltype(k)}, indices(v,1)), v, k; kwargs..., initialized=false) """ - selectperm!(ix, v, k, [alg=,] [by=,] [lt=,] [rev=false,] [initialized=false]) + partialsortperm!(ix, v, k, [alg=,] [by=,] [lt=,] [rev=false,] [initialized=false]) -Like [`selectperm`](@ref), but accepts a preallocated index vector `ix`. If `initialized` is `false` +Like [`partialsortperm`](@ref), but accepts a preallocated index vector `ix`. If `initialized` is `false` (the default), ix is initialized to contain the values `1:length(ix)`. """ -function selectperm!(ix::AbstractVector{<:Integer}, v::AbstractVector, - k::Union{Int, OrdinalRange}; - lt::Function=isless, - by::Function=identity, - rev::Bool=false, - order::Ordering=Forward, - initialized::Bool=false) +function partialsortperm!(ix::AbstractVector{<:Integer}, v::AbstractVector, + k::Union{Int, OrdinalRange}; + lt::Function=isless, + by::Function=identity, + rev::Bool=false, + order::Ordering=Forward, + initialized::Bool=false) if !initialized @inbounds for i = indices(ix,1) ix[i] = i diff --git a/base/statistics.jl b/base/statistics.jl index b15669fc9bf90..226a8661a85f1 100644 --- a/base/statistics.jl +++ b/base/statistics.jl @@ -599,9 +599,9 @@ function median!(v::AbstractVector) n = length(inds) mid = div(first(inds)+last(inds),2) if isodd(n) - return middle(select!(v,mid)) + return middle(partialsort!(v,mid)) else - m = select!(v, mid:mid+1) + m = partialsort!(v, mid:mid+1) return middle(m[1], m[2]) end end diff --git a/doc/src/stdlib/sort.md b/doc/src/stdlib/sort.md index 65bfd0e70bbc9..ffb4725b6bcf6 100644 --- a/doc/src/stdlib/sort.md +++ b/doc/src/stdlib/sort.md @@ -122,10 +122,10 @@ Base.issorted Base.Sort.searchsorted Base.Sort.searchsortedfirst Base.Sort.searchsortedlast -Base.Sort.select! -Base.Sort.select -Base.Sort.selectperm -Base.Sort.selectperm! +Base.Sort.partialsort! +Base.Sort.partialsort +Base.Sort.partialsortperm +Base.Sort.partialsortperm! ``` ## Sorting Algorithms diff --git a/test/core.jl b/test/core.jl index 08c3986562915..d9b80655bd0ae 100644 --- a/test/core.jl +++ b/test/core.jl @@ -3765,11 +3765,11 @@ end module M15455 function rpm_provides(r::T) where T - push!([], select(r,T)) + push!([], partialsort(r,T)) end -select(a,b) = 0 +partialsort(a,b) = 0 end -@test M15455.select(1,2)==0 +@test M15455.partialsort(1,2)==0 # check that medium-sized array is 64-byte aligned (#15139) @test Int(pointer(Vector{Float64}(1024))) % 64 == 0 diff --git a/test/ranges.jl b/test/ranges.jl index 19e082e97819b..e34fbad8628d7 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -314,7 +314,7 @@ end @test sort!(UnitRange(1,2)) == UnitRange(1,2) @test sort(1:10, rev=true) == collect(10:-1:1) @test sort(-3:3, by=abs) == [0,-1,1,-2,2,-3,3] -@test select(1:10, 4) == 4 +@test partialsort(1:10, 4) == 4 @test 0 in UInt(0):100:typemax(UInt) @test last(UInt(0):100:typemax(UInt)) in UInt(0):100:typemax(UInt) diff --git a/test/sorting.jl b/test/sorting.jl index 28d7020d25458..cc5545e353d04 100644 --- a/test/sorting.jl +++ b/test/sorting.jl @@ -17,16 +17,16 @@ end @test !issorted([2,3,1]) @test issorted([1,2,3]) @test reverse([2,3,1]) == [1,3,2] -@test select([3,6,30,1,9],3) == 6 -@test select([3,6,30,1,9],3:4) == [6,9] -@test selectperm([3,6,30,1,9], 3:4) == [2,5] -@test selectperm!(collect(1:5), [3,6,30,1,9], 3:4) == [2,5] +@test partialsort([3,6,30,1,9],3) == 6 +@test partialsort([3,6,30,1,9],3:4) == [6,9] +@test partialsortperm([3,6,30,1,9], 3:4) == [2,5] +@test partialsortperm!(collect(1:5), [3,6,30,1,9], 3:4) == [2,5] let a=[1:10;] for r in Any[2:4, 1:2, 10:10, 4:2, 2:1, 4:-1:2, 2:-1:1, 10:-1:10, 4:1:3, 1:2:8, 10:-3:1] - @test select(a, r) == [r;] - @test selectperm(a, r) == [r;] - @test select(a, r, rev=true) == (11 .- [r;]) - @test selectperm(a, r, rev=true) == (11 .- [r;]) + @test partialsort(a, r) == [r;] + @test partialsortperm(a, r) == [r;] + @test partialsort(a, r, rev=true) == (11 .- [r;]) + @test partialsortperm(a, r, rev=true) == (11 .- [r;]) end end @test sum(randperm(6)) == 21 @@ -204,10 +204,10 @@ let alg = PartialQuickSort(div(length(a), 10)) @test !issorted(d, rev=true) end -@test select([3,6,30,1,9], 2, rev=true) == 9 -@test select([3,6,30,1,9], 2, by=x->1/x) == 9 -@test selectperm([3,6,30,1,9], 2, rev=true) == 5 -@test selectperm([3,6,30,1,9], 2, by=x->1/x) == 5 +@test partialsort([3,6,30,1,9], 2, rev=true) == 9 +@test partialsort([3,6,30,1,9], 2, by=x->1/x) == 9 +@test partialsortperm([3,6,30,1,9], 2, rev=true) == 5 +@test partialsortperm([3,6,30,1,9], 2, by=x->1/x) == 5 ## more advanced sorting tests ## From 8150f666fd76a6098e12f235ea8fbf7246867e9e Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Mon, 31 Jul 2017 16:13:07 +0200 Subject: [PATCH 2/3] Make partialsort!() and partialsortperm!() return a view rather than a copy Returning a copy (partially) defeats the purpose of these functions, which is to avoid allocations. --- base/deprecated.jl | 8 ++++---- base/sort.jl | 14 ++++++++++++-- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index 238fab1ae71b8..b7d6ff7e613f5 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -1743,10 +1743,10 @@ end @deprecate IOContext(io::IO, key, value) IOContext(io, key=>value) # issue #22791 -@deprecate_binding select partialsort -@deprecate_binding select! partialsort! -@deprecate_binding selectperm partialsortperm -@deprecate_binding selectperm! partialsortperm! +@deprecate select partialsort +@deprecate select! partialsort! +@deprecate selectperm partialsortperm +@deprecate selectperm! partialsortperm! # END 0.7 deprecations diff --git a/base/sort.jl b/base/sort.jl index 7930f856f2f92..16910be31f2db 100644 --- a/base/sort.jl +++ b/base/sort.jl @@ -85,7 +85,12 @@ issorted(itr; function partialsort!(v::AbstractVector, k::Union{Int,OrdinalRange}, o::Ordering) inds = indices(v, 1) sort!(v, first(inds), last(inds), PartialQuickSort(k), o) - v[k] + + if k isa Integer + return v[k] + else + return view(v, k) + end end """ @@ -706,7 +711,12 @@ function partialsortperm!(ix::AbstractVector{<:Integer}, v::AbstractVector, # do partial quicksort sort!(ix, PartialQuickSort(k), Perm(ord(lt, by, rev, order), v)) - return ix[k] + + if k isa Integer + return ix[k] + else + return view(ix, k) + end end ## sortperm: the permutation to sort an array ## From 7a54a2f827f78940ef21324499b4667493222e5e Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Fri, 25 Aug 2017 17:43:27 +0200 Subject: [PATCH 3/3] Fix docstrings for partialsortperm() and partialsortperm!() partialsort(x, k::Integer), partialsortperm(x, k::Integer) and partialsortperm!(x, k::Integer) all return a single value. Also add missing backticks. --- base/sort.jl | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/base/sort.jl b/base/sort.jl index 16910be31f2db..cb28e79d7de52 100644 --- a/base/sort.jl +++ b/base/sort.jl @@ -680,12 +680,12 @@ sort(v::AbstractVector; kws...) = sort!(copymutable(v); kws...) Return a partial permutation of the vector `v`, according to the order specified by `by`, `lt` and `rev`, so that `v[output]` returns the first `k` (or range of adjacent values -if `k` is a range) values of a fully sorted version of `v`. If `k` is a single index -(Integer), an array of the first `k` indices is returned; if `k` is a range, an array of -those indices is returned. Note that the handling of integer values for `k` is different -from [`select`](@ref) in that it returns a vector of `k` elements instead of just the `k` th -element. Also note that this is equivalent to, but more efficient than, calling -`sortperm(...)[k]`. +if `k` is a range) values of a fully sorted version of `v`. If `k` is a single index, +the index in `v` of the value which would be sorted at position `k` is returned; +if `k` is a range, an array with the indices in `v` of the values which would be sorted in +these positions is returned. + +Note that this is equivalent to, but more efficient than, calling `sortperm(...)[k]`. """ partialsortperm(v::AbstractVector, k::Union{Integer,OrdinalRange}; kwargs...) = partialsortperm!(similar(Vector{eltype(k)}, indices(v,1)), v, k; kwargs..., initialized=false) @@ -694,7 +694,7 @@ partialsortperm(v::AbstractVector, k::Union{Integer,OrdinalRange}; kwargs...) = partialsortperm!(ix, v, k, [alg=,] [by=,] [lt=,] [rev=false,] [initialized=false]) Like [`partialsortperm`](@ref), but accepts a preallocated index vector `ix`. If `initialized` is `false` -(the default), ix is initialized to contain the values `1:length(ix)`. +(the default), `ix` is initialized to contain the values `1:length(ix)`. """ function partialsortperm!(ix::AbstractVector{<:Integer}, v::AbstractVector, k::Union{Int, OrdinalRange};