Skip to content

Commit f5d936b

Browse files
add keepat! for in-place logical filtering
Co-authored-by: Jameson Nash <vtjnash@gmail.com> Co-authored-by: Jeff Bezanson <jeff.bezanson@gmail.com>
1 parent deb3fac commit f5d936b

File tree

4 files changed

+85
-23
lines changed

4 files changed

+85
-23
lines changed

base/abstractarray.jl

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3067,29 +3067,7 @@ end
30673067

30683068
## keepat! ##
30693069

3070-
"""
3071-
keepat!(a::AbstractVector, inds)
3072-
3073-
Remove the items at all the indices which are not given by `inds`,
3074-
and return the modified `a`.
3075-
Items which are kept are shifted to fill the resulting gaps.
3076-
3077-
`inds` must be an iterator of sorted and unique integer indices.
3078-
See also [`deleteat!`](@ref).
3079-
3080-
!!! compat "Julia 1.7"
3081-
This function is available as of Julia 1.7.
3082-
3083-
# Examples
3084-
```jldoctest
3085-
julia> keepat!([6, 5, 4, 3, 2, 1], 1:2:5)
3086-
3-element Vector{Int64}:
3087-
6
3088-
4
3089-
2
3090-
```
3091-
"""
3092-
function keepat!(a::AbstractVector, inds)
3070+
function _keepat!(a::AbstractVector, inds)
30933071
local prev
30943072
i = firstindex(a)
30953073
for k in inds
@@ -3106,3 +3084,18 @@ function keepat!(a::AbstractVector, inds)
31063084
deleteat!(a, i:lastindex(a))
31073085
return a
31083086
end
3087+
3088+
function _keepat!(a::AbstractVector, m::AbstractVector{Bool})
3089+
j = firstindex(a)
3090+
for i in eachindex(a, m)
3091+
@inbounds begin
3092+
if m[i]
3093+
i == j || (a[j] = a[i])
3094+
j = nextind(a, j)
3095+
end
3096+
end
3097+
end
3098+
j > lastindex(a) && return a
3099+
deleteat!(a, j:lastindex(a))
3100+
return a
3101+
end

base/array.jl

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2602,6 +2602,54 @@ function filter!(f, a::AbstractVector)
26022602
return a
26032603
end
26042604

2605+
"""
2606+
keepat!(a::Vector, inds)
2607+
2608+
Remove the items at all the indices which are not given by `inds`,
2609+
and return the modified `a`.
2610+
Items which are kept are shifted to fill the resulting gaps.
2611+
2612+
`inds` must be an iterator of sorted and unique integer indices.
2613+
See also [`deleteat!`](@ref).
2614+
2615+
!!! compat "Julia 1.7"
2616+
This function is available as of Julia 1.7.
2617+
2618+
# Examples
2619+
```jldoctest
2620+
julia> keepat!([6, 5, 4, 3, 2, 1], 1:2:5)
2621+
3-element Vector{Int64}:
2622+
6
2623+
4
2624+
2
2625+
```
2626+
"""
2627+
keepat!(a::Vector, inds) = _keepat!(a, inds)
2628+
2629+
"""
2630+
keepat!(a::Vector, m::AbstractVector{Bool})
2631+
2632+
The in-place version of logical indexing `a = a[m]`. That is, `keepat!(a, m)` on
2633+
vectors of equal length `a` and `m` will remove all elements from `a` for which
2634+
`m` at the corresponding index is `false`.
2635+
2636+
# Examples
2637+
```jldoctest
2638+
julia> a = [:a, :b, :c];
2639+
2640+
julia> keepat!(a, [true, false, true])
2641+
2-element Vector{Symbol}:
2642+
:a
2643+
:c
2644+
2645+
julia> a
2646+
2-element Vector{Symbol}:
2647+
:a
2648+
:c
2649+
```
2650+
"""
2651+
keepat!(a::Vector, m::AbstractVector{Bool}) = _keepat!(a, m)
2652+
26052653
# set-like operators for vectors
26062654
# These are moderately efficient, preserve order, and remove dupes.
26072655

base/bitarray.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1063,6 +1063,9 @@ function deleteat!(B::BitVector, inds::AbstractVector{Bool})
10631063
return B
10641064
end
10651065

1066+
keepat!(B::BitVector, inds) = _keepat!(B, inds)
1067+
keepat!(B::BitVector, inds::AbstractVector{Bool}) = _keepat!(B, inds)
1068+
10661069
function splice!(B::BitVector, i::Integer)
10671070
# TODO: after deprecation remove the four lines below
10681071
# as v = B[i] is enough to do both bounds checking

test/arrayops.jl

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1457,6 +1457,24 @@ end
14571457
@test isempty(eoa)
14581458
end
14591459

1460+
@testset "logical keepat!" begin
1461+
# Vector
1462+
a = Vector(1:10)
1463+
keepat!(a, [falses(5); trues(5)])
1464+
@test a == 6:10
1465+
1466+
# BitVector
1467+
ba = rand(10) .> 0.5
1468+
@test isa(ba, BitArray)
1469+
keepat!(ba, ba)
1470+
@test all(ba)
1471+
1472+
# empty array
1473+
ea = []
1474+
keepat!(ea, Bool[])
1475+
@test isempty(ea)
1476+
end
1477+
14601478
@testset "deleteat!" begin
14611479
for idx in Any[1, 2, 5, 9, 10, 1:0, 2:1, 1:1, 2:2, 1:2, 2:4, 9:8, 10:9, 9:9, 10:10,
14621480
8:9, 9:10, 6:9, 7:10]

0 commit comments

Comments
 (0)