Skip to content
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

Add insorted for in function in sorted arrays #37490

Merged
merged 16 commits into from
Sep 28, 2020
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,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 @@ -457,6 +457,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 @@ -1063,7 +1063,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
in sorted collections.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
in sorted collections.
with sorted collections.

?

Copy link
Member

Choose a reason for hiding this comment

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

One last comment, maybe a native speaker could quickly help, and then we merge this.


The returned function is of type `Base.Fix2{typeof(in)}`, which can be
used to implement specialized methods.
Expand Down
36 changes: 36 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,41 @@ julia> searchsortedlast([1, 2, 4, 5, 5, 7], 0) # no match, insert at start
```
""" searchsortedlast

function insorted end
insorted(x, v::AbstractVector; kw...) = !isempty(searchsorted(v, x, kw...))
insorted(x, r::AbstractRange) = in(x, r)

"""
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
```
remi-garcia marked this conversation as resolved.
Show resolved Hide resolved

!!! compat "Julia 1.6"
`insorted` was added in Julia 1.6.
""" insorted
remi-garcia marked this conversation as resolved.
Show resolved Hide resolved


## 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
58 changes: 58 additions & 0 deletions test/sorting.jl
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,64 @@ Base.step(r::ConstantRange) = 0
end
end
end
@testset "insorted" begin
remi-garcia marked this conversation as resolved.
Show resolved Hide resolved
numTypes = [ Int8, Int16, Int32, Int64, Int128,
UInt8, UInt16, UInt32, UInt64, UInt128,
Float16, Float32, Float64, BigInt, BigFloat]

@test insorted(1, [1:10;], by=(x -> x >= 5)) == true
@test insorted(10, [1:10;], by=(x -> x >= 5)) == true
@test insorted(1, [1:5; 1:5; 1:5], 6, 10, Forward) == true
@test insorted(1, fill(1, 15), 6, 10, Forward) == true

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

@test insorted(T(0), 1:3) === false
@test insorted(T(1), 1:3) == true
@test insorted(T(2), 1:3) == true
@test insorted(T(4), 1:3) === false

@test insorted(T(1), R[1:10;], by=(x -> x >= 5)) == true
@test insorted(T(10), R[1:10;], by=(x -> x >= 5)) == true
@test insorted(T(1), R[1:5; 1:5; 1:5], 6, 10, Forward) == true
@test insorted(T(1), fill(R(1), 15), 6, 10, Forward) == true
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 = [rg;], [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) == true
@test insorted(prevfloat(rg[i]), rg) === false
@test insorted(nextfloat(rg[i]), rg) === false
end

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

@test insorted(1, 1:10) == insorted(1, [1:10;], by=(x -> x >= 5))
@test insorted(10, 1:10) == insorted(10, [1:10;], by=(x -> x >= 5))

@test insorted(0, []) === false
@test insorted(0, [1,2,3]) === false
@test insorted(4, [1,2,3]) === false
end
@testset "PartialQuickSort" begin
a = rand(1:10000, 1000)
# test PartialQuickSort only does a partial sort
Expand Down