Skip to content

Commit 8e62a99

Browse files
JeffBezansonMasonProtter
authored andcommitted
add keepat! for in-place logical filtering (#42351)
Co-authored-by: Jameson Nash <[email protected]> Co-authored-by: MasonProtter <[email protected]>
1 parent 3735240 commit 8e62a99

File tree

4 files changed

+88
-22
lines changed

4 files changed

+88
-22
lines changed

base/abstractarray.jl

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3067,29 +3067,9 @@ 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).
3070+
# NOTE: since these use `@inbounds`, they are actually only intended for Vector and BitVector
30793071

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)
3072+
function _keepat!(a::AbstractVector, inds)
30933073
local prev
30943074
i = firstindex(a)
30953075
for k in inds
@@ -3106,3 +3086,18 @@ function keepat!(a::AbstractVector, inds)
31063086
deleteat!(a, i:lastindex(a))
31073087
return a
31083088
end
3089+
3090+
function _keepat!(a::AbstractVector, m::AbstractVector{Bool})
3091+
length(m) == length(a) || throw(BoundsError(a, m))
3092+
j = firstindex(a)
3093+
for i in eachindex(a, m)
3094+
@inbounds begin
3095+
if m[i]
3096+
i == j || (a[j] = a[i])
3097+
j = nextind(a, j)
3098+
end
3099+
end
3100+
end
3101+
deleteat!(a, j:lastindex(a))
3102+
return a
3103+
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: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1457,6 +1457,26 @@ 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+
@test_throws BoundsError keepat!(a, trues(1))
1466+
@test_throws BoundsError keepat!(a, trues(11))
1467+
1468+
# BitVector
1469+
ba = rand(10) .> 0.5
1470+
@test isa(ba, BitArray)
1471+
keepat!(ba, ba)
1472+
@test all(ba)
1473+
1474+
# empty array
1475+
ea = []
1476+
keepat!(ea, Bool[])
1477+
@test isempty(ea)
1478+
end
1479+
14601480
@testset "deleteat!" begin
14611481
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,
14621482
8:9, 9:10, 6:9, 7:10]

0 commit comments

Comments
 (0)