Skip to content

Commit

Permalink
add keepat! (#770)
Browse files Browse the repository at this point in the history
  • Loading branch information
bkamins authored May 23, 2022
1 parent 42baeea commit cad1700
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 12 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "Compat"
uuid = "34da2185-b29b-5c13-b0c7-acf172513d20"
version = "4.0.0"
version = "4.1.0"

[deps]
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ changes in `julia`.

## Supported features

* `keepat!` removes the items at all the indices which are not given and returns
the modified source ([#36229], [#42351]). (since Compat 4.1.0)

* `@compat (; a, b) = (; c=1, b=2, a=3)` supports property descturing assignment syntax ([#39285]).

* `allequal`, the opposite of `allunique` ([#43354]). (since Compat 3.42.0)
Expand Down Expand Up @@ -133,6 +136,7 @@ Note that you should specify the correct minimum version for `Compat` in the

[#29901]: https://github.com/JuliaLang/julia/issues/29901
[#35316]: https://github.com/JuliaLang/julia/issues/35316
[#36229]: https://github.com/JuliaLang/julia/issues/36229
[#39037]: https://github.com/JuliaLang/julia/issues/39037
[#39245]: https://github.com/JuliaLang/julia/issues/39245
[#39285]: https://github.com/JuliaLang/julia/issues/39285
Expand All @@ -144,4 +148,5 @@ Note that you should specify the correct minimum version for `Compat` in the
[#41076]: https://github.com/JuliaLang/julia/issues/41076
[#41312]: https://github.com/JuliaLang/julia/issues/41312
[#42125]: https://github.com/JuliaLang/julia/issues/42125
[#42351]: https://github.com/JuliaLang/julia/issues/42351
[#43354]: https://github.com/JuliaLang/julia/issues/43354
60 changes: 51 additions & 9 deletions src/Compat.jl
Original file line number Diff line number Diff line change
Expand Up @@ -235,9 +235,9 @@ if VERSION < v"1.8.0-DEV.300"
end

# https://github.com/JuliaLang/julia/pull/39245
if VERSION < v"1.8.0-DEV.487"
if VERSION < v"1.8.0-DEV.487"
export eachsplit

"""
eachsplit(str::AbstractString, dlm; limit::Integer=0)
eachsplit(str::AbstractString; limit::Integer=0)
Expand All @@ -246,14 +246,14 @@ if VERSION < v"1.8.0-DEV.487"
substrings. `dlm` can be any of the formats allowed by [`findnext`](@ref)'s first argument
(i.e. as a string, regular expression or a function), or as a single character or collection
of characters.
If `dlm` is omitted, it defaults to [`isspace`](@ref).
The iterator will return a maximum of `limit` results if the keyword argument is supplied.
The default of `limit=0` implies no maximum.
See also [`split`](@ref).
# Examples
```julia
julia> a = "Ma.rch"
Expand All @@ -265,7 +265,7 @@ if VERSION < v"1.8.0-DEV.487"
```
"""
function eachsplit end

struct SplitIterator{S<:AbstractString,F}
str::S
splitter::F
Expand All @@ -275,13 +275,13 @@ if VERSION < v"1.8.0-DEV.487"

Base.eltype(::Type{<:SplitIterator}) = SubString
Base.IteratorSize(::Type{<:SplitIterator}) = Base.SizeUnknown()

function Base.iterate(iter::SplitIterator, (i, k, n)=(firstindex(iter.str), firstindex(iter.str), 0))
i - 1 > ncodeunits(iter.str)::Int && return nothing
r = findnext(iter.splitter, iter.str, k)::Union{Nothing,Int,UnitRange{Int}}
while r !== nothing && n != iter.limit - 1 && first(r) <= ncodeunits(iter.str)
r = r::Union{Int,UnitRange{Int}} #commit dcc2182db228935fe97d03a44ae3b6889e40c542
#follow #39245, improve inferrability of iterate(::SplitIterator)
#follow #39245, improve inferrability of iterate(::SplitIterator)
#Somehow type constraints from the complex `while` condition don't
#propagate to the `while` body.
j, k = first(r), nextind(iter.str, last(r))::Int
Expand Down Expand Up @@ -320,6 +320,48 @@ if VERSION < v"1.8.0-DEV.1494" # 98e60ffb11ee431e462b092b48a31a1204bd263d
allequal(r::AbstractRange) = iszero(step(r)) || length(r) <= 1
end

# This function is available as of Julia 1.7.
@static if !isdefined(Base, :keepat!)
export keepat!

keepat!(B::BitVector, inds) = _keepat!(B, inds)
keepat!(B::BitVector, inds::AbstractVector{Bool}) = _keepat!(B, inds)
keepat!(a::Vector, inds) = _keepat!(a, inds)
keepat!(a::Vector, m::AbstractVector{Bool}) = _keepat!(a, m)

function _keepat!(a::AbstractVector, inds)
local prev
i = firstindex(a)
for k in inds
if @isdefined(prev)
prev < k || throw(ArgumentError("indices must be unique and sorted"))
end
ak = a[k] # must happen even when i==k for bounds checking
if i != k
@inbounds a[i] = ak # k > i, so a[i] is inbounds
end
prev = k
i = nextind(a, i)
end
deleteat!(a, i:lastindex(a))
return a
end

function _keepat!(a::AbstractVector, m::AbstractVector{Bool})
length(m) == length(a) || throw(BoundsError(a, m))
j = firstindex(a)
for i in eachindex(a, m)
@inbounds begin
if m[i]
i == j || (a[j] = a[i])
j = nextind(a, j)
end
end
end
deleteat!(a, j:lastindex(a))
end
end

include("deprecated.jl")

end # module Compat
42 changes: 40 additions & 2 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -312,8 +312,8 @@ end
#=
cmcaine commented on Sep 8, 2021
This PR implements split with eachsplit and uses eachsplit in a few other places in Base,
so it's kind of already covered by the existing tests.
This PR implements split with eachsplit and uses eachsplit in a few other places in Base,
so it's kind of already covered by the existing tests.
Not sure it needs any more?
so, these are the Base.split tests, but replacing split with eachsplit |> collect
Expand Down Expand Up @@ -409,3 +409,41 @@ end
@test !allequal(LinRange(1, 2, 2))
end

@testset "keepat!" begin
a = [1:6;]
@test a === keepat!(a, 1:5)
@test a == 1:5
@test keepat!(a, [2, 4]) == [2, 4]
@test isempty(keepat!(a, []))

a = [1:6;]
@test_throws BoundsError keepat!(a, 1:10) # make sure this is not a no-op
@test_throws BoundsError keepat!(a, 2:10)
@test_throws ArgumentError keepat!(a, [2, 4, 3])

b = BitVector([1, 1, 1, 0, 0])
@test b === keepat!(b, 1:5)
@test b == [1, 1, 1, 0, 0]
@test keepat!(b, 2:4) == [1, 1, 0]
@test_throws BoundsError keepat!(a, -1:10)
@test_throws ArgumentError keepat!(a, [2, 1])
@test isempty(keepat!(a, []))

# Vector
a = Vector(1:10)
keepat!(a, [falses(5); trues(5)])
@test a == 6:10
@test_throws BoundsError keepat!(a, trues(1))
@test_throws BoundsError keepat!(a, trues(11))

# BitVector
ba = rand(10) .> 0.5
@test isa(ba, BitArray)
keepat!(ba, ba)
@test all(ba)

# empty array
ea = []
keepat!(ea, Bool[])
@test isempty(ea)
end

4 comments on commit cad1700

@martinholters
Copy link
Member

Choose a reason for hiding this comment

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

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

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

Registration pull request created: JuliaRegistries/General/60831

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v4.1.0 -m "<description of version>" cad170038b8c63ba8c4b37c7cba62455bba4c368
git push origin v4.1.0

@johnnychen94
Copy link
Member

Choose a reason for hiding this comment

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

By yanking 4.0 release, I thought we need to revert back to 3.x versions JuliaRegistries/General#60317

cc: @KristofferC

@martinholters
Copy link
Member

Choose a reason for hiding this comment

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

See discussion in #767. For a transition period, we will be maintaining a branch for further v3.x releases where features are backported needed by someone who cannot for whatever reason (e.g. needing to support Julia prior to 1.6 or a dependency not compatible with Compat v4) require Compat v4.

Please sign in to comment.