-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rename select* functions to partialsort* and various related fixes #23051
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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,25 @@ 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] | ||
|
||
if k isa Integer | ||
return v[k] | ||
else | ||
return view(v, k) | ||
end | ||
end | ||
|
||
""" | ||
select!(v, k, [by=<transform>,] [lt=<comparison>,] [rev=false]) | ||
partialsort!(v, k, [by=<transform>,] [lt=<comparison>,] [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 +113,7 @@ julia> a = [1, 2, 4, 3, 4] | |
3 | ||
4 | ||
|
||
julia> select!(a, 4) | ||
julia> partialsort!(a, 4) | ||
4 | ||
|
||
julia> a | ||
|
@@ -127,7 +132,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 +144,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=<transform>,] [lt=<comparison>,] [rev=false]) | ||
partialsort(v, k, [by=<transform>,] [lt=<comparison>,] [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,36 +673,36 @@ 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=<algorithm>,] [by=<transform>,] [lt=<comparison>,] [rev=false]) | ||
partialsortperm(v, k, [alg=<algorithm>,] [by=<transform>,] [lt=<comparison>,] [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 | ||
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]`. | ||
""" | ||
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=<algorithm>,] [by=<transform>,] [lt=<comparison>,] [rev=false,] [initialized=false]) | ||
partialsortperm!(ix, v, k, [alg=<algorithm>,] [by=<transform>,] [lt=<comparison>,] [rev=false,] [initialized=false]) | ||
|
||
Like [`selectperm`](@ref), but accepts a preallocated index vector `ix`. If `initialized` is `false` | ||
(the default), ix is initialized to contain the values `1:length(ix)`. | ||
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 | ||
|
@@ -705,7 +711,12 @@ function selectperm!(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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Likewise here, perhaps using dispatch for this purpose would be better than branching? |
||
return ix[k] | ||
else | ||
return view(ix, k) | ||
end | ||
end | ||
|
||
## sortperm: the permutation to sort an array ## | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps using dispatch for this logic would be better than branching?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general I'd agree with you, but in the present case that would force duplicating the two lines above, that's why I chose the
if
approach.BTW, there seems to be a lack in the API: with
getindex
, you can either get an array or a scalar, but withview
/@view
you always get a subarray. Shouldn't there be a way to get the same behavior asgetindex
? Then one wouldn't have to check types manually like this (which could be hard or impossible in more complex cases where the index can be of any type.)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would not
do the trick? Could even reuse the helper functions for the same purpose below :).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess that would work, but I don't find it clearer than the existing version, do you? To understand what the code does you need to look at the definitions of methods for
_dispatchftw
, which does not have a generic meaning on its own.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Noting that my subjective evaluation is practically meaningless, yes, I prefer this style :).
Perhaps a more meaningful question would be whether one or the approach is friendlier to the compiler?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is always the third option, with the same lines of code:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The harsh reality is, not all lines of code are equal.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea, I'm voting for status quo or perhaps change it to using the ternary operator.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's go with the current version then. I've rebased again, let's not wait for too long as there were already substantial conflicts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually,
@views
seems to do the trick. See #23760.