Skip to content

Commit

Permalink
Add insorted for in function in sorted arrays (#37490)
Browse files Browse the repository at this point in the history
  • Loading branch information
remi-garcia authored Sep 28, 2020
1 parent 6596f95 commit f6d1032
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 1 deletion.
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ New library functions
* New function `sincospi` for simultaneously computing `sinpi(x)` and `cospi(x)` more
efficiently ([#35816]).
* New function `addenv` for adding environment mappings into a `Cmd` object, returning the new `Cmd` object.
* New function `insorted` for determining whether an element is in a sorted collection or not ([#37490]).

New library features
--------------------
Expand Down
1 change: 1 addition & 0 deletions base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,7 @@ export
searchsorted,
searchsortedfirst,
searchsortedlast,
insorted,
startswith,

# linear algebra
Expand Down
3 changes: 2 additions & 1 deletion base/operators.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1095,7 +1095,8 @@ splat(f) = args->f(args...)
in(x)
Create a function that checks whether its argument is [`in`](@ref) `x`, i.e.
a function equivalent to `y -> y in x`.
a function equivalent to `y -> y in x`. See also [`insorted`](@ref) for the use
with sorted collections.
The returned function is of type `Base.Fix2{typeof(in)}`, which can be
used to implement specialized methods.
Expand Down
34 changes: 34 additions & 0 deletions base/sort.jl
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export # also exported by Base
searchsorted,
searchsortedfirst,
searchsortedlast,
insorted,
# order & algorithm:
sort,
sort!,
Expand Down Expand Up @@ -407,6 +408,39 @@ julia> searchsortedlast([1, 2, 4, 5, 5, 7], 0) # no match, insert at start
```
""" searchsortedlast

"""
insorted(a, x; by=<transform>, lt=<comparison>, rev=false)
Determine whether an item is in the given sorted collection, in the sense that
it is [`==`](@ref) to one of the values of the collection according to the order
specified by the `by`, `lt` and `rev` keywords, assuming that `a` is already
sorted in that order, see [`sort`](@ref) for the keywords. See also
[`in`](@ref). Returns a `Bool` value.
# Examples
```jldoctest
julia> insorted(4, [1, 2, 4, 5, 5, 7]) # single match
true
julia> insorted(5, [1, 2, 4, 5, 5, 7]) # multiple matches
true
julia> insorted(3, [1, 2, 4, 5, 5, 7]) # no match
false
julia> insorted(9, [1, 2, 4, 5, 5, 7]) # no match
false
julia> insorted(0, [1, 2, 4, 5, 5, 7]) # no match
false
```
!!! compat "Julia 1.6"
`insorted` was added in Julia 1.6.
"""
function insorted end
insorted(x, v::AbstractVector; kw...) = !isempty(searchsorted(v, x; kw...))
insorted(x, r::AbstractRange) = in(x, r)

## sorting algorithms ##

Expand Down
1 change: 1 addition & 0 deletions doc/src/base/sort.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ Base.issorted
Base.Sort.searchsorted
Base.Sort.searchsortedfirst
Base.Sort.searchsortedlast
Base.Sort.insorted
Base.Sort.partialsort!
Base.Sort.partialsort
Base.Sort.partialsortperm
Expand Down
55 changes: 55 additions & 0 deletions test/sorting.jl
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,61 @@ Base.step(r::ConstantRange) = 0
end
end
end
@testset "insorted" begin
numTypes = [Int8, Int16, Int32, Int64, Int128,
UInt8, UInt16, UInt32, UInt64, UInt128,
Float16, Float32, Float64, BigInt, BigFloat]

@test insorted(1, collect(1:10), by=(>=(5)))
@test insorted(10, collect(1:10), by=(>=(5)))

for R in numTypes, T in numTypes
@test !insorted(T(0), R[1, 1, 2, 2, 3, 3])
@test insorted(T(1), R[1, 1, 2, 2, 3, 3])
@test insorted(T(2), R[1, 1, 2, 2, 3, 3])
@test !insorted(T(4), R[1, 1, 2, 2, 3, 3])
@test !insorted(2.5, R[1, 1, 2, 2, 3, 3])

@test !insorted(T(0), 1:3)
@test insorted(T(1), 1:3)
@test insorted(T(2), 1:3)
@test !insorted(T(4), 1:3)

@test insorted(T(1), R.(collect(1:10)), by=(>=(5)))
@test insorted(T(10), R.(collect(1:10)), by=(>=(5)))
end

for (rg,I) in [(49:57,47:59), (1:2:17,-1:19), (-3:0.5:2,-5:.5:4)]
rg_r = reverse(rg)
rgv, rgv_r = collect(rg), collect(rg_r)
for i = I
@test insorted(i,rg) === insorted(i,rgv)
@test insorted(i,rg_r) === insorted(i,rgv_r,rev=true)
end
end

rg = 0.0:0.01:1.0
for i = 2:101
@test insorted(rg[i], rg)
@test !insorted(prevfloat(rg[i]), rg)
@test !insorted(nextfloat(rg[i]), rg)
end

rg_r = reverse(rg)
for i = 1:100
@test insorted(rg_r[i], rg_r)
@test !insorted(prevfloat(rg_r[i]), rg_r)
@test !insorted(nextfloat(rg_r[i]), rg_r)
end

@test insorted(1, 1:10) == insorted(1, collect(1:10), by=(>=(5)))
@test insorted(10, 1:10) == insorted(10, collect(1:10), by=(>=(5)))

@test !insorted(0, [])
@test !insorted(0, [1,2,3])
@test !insorted(4, [1,2,3])
@test insorted(3, [10,8,6,9,4,7,2,5,3,1], by=(x -> iseven(x) ? x+5 : x), rev=true)
end
@testset "PartialQuickSort" begin
a = rand(1:10000, 1000)
# test PartialQuickSort only does a partial sort
Expand Down

2 comments on commit f6d1032

@nanosoldier
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Executing the daily benchmark build, I will reply here when finished:

@nanosoldier runbenchmarks(ALL, isdaily = true)

@nanosoldier
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your benchmark job has completed - possible performance regressions were detected. A full report can be found here. cc @ararslan

Please sign in to comment.