Skip to content

Commit b97fde6

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]> (cherry picked from commit b9fba13)
1 parent 8ebf8fd commit b97fde6

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
@@ -3040,29 +3040,9 @@ end
30403040

30413041
## keepat! ##
30423042

3043-
"""
3044-
keepat!(a::AbstractVector, inds)
3045-
3046-
Remove the items at all the indices which are not given by `inds`,
3047-
and return the modified `a`.
3048-
Items which are kept are shifted to fill the resulting gaps.
3049-
3050-
`inds` must be an iterator of sorted and unique integer indices.
3051-
See also [`deleteat!`](@ref).
3043+
# NOTE: since these use `@inbounds`, they are actually only intended for Vector and BitVector
30523044

3053-
!!! compat "Julia 1.7"
3054-
This function is available as of Julia 1.7.
3055-
3056-
# Examples
3057-
```jldoctest
3058-
julia> keepat!([6, 5, 4, 3, 2, 1], 1:2:5)
3059-
3-element Vector{Int64}:
3060-
6
3061-
4
3062-
2
3063-
```
3064-
"""
3065-
function keepat!(a::AbstractVector, inds)
3045+
function _keepat!(a::AbstractVector, inds)
30663046
local prev
30673047
i = firstindex(a)
30683048
for k in inds
@@ -3079,3 +3059,18 @@ function keepat!(a::AbstractVector, inds)
30793059
deleteat!(a, i:lastindex(a))
30803060
return a
30813061
end
3062+
3063+
function _keepat!(a::AbstractVector, m::AbstractVector{Bool})
3064+
length(m) == length(a) || throw(BoundsError(a, m))
3065+
j = firstindex(a)
3066+
for i in eachindex(a, m)
3067+
@inbounds begin
3068+
if m[i]
3069+
i == j || (a[j] = a[i])
3070+
j = nextind(a, j)
3071+
end
3072+
end
3073+
end
3074+
deleteat!(a, j:lastindex(a))
3075+
return a
3076+
end

base/array.jl

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2528,6 +2528,54 @@ function filter!(f, a::AbstractVector)
25282528
return a
25292529
end
25302530

2531+
"""
2532+
keepat!(a::Vector, inds)
2533+
2534+
Remove the items at all the indices which are not given by `inds`,
2535+
and return the modified `a`.
2536+
Items which are kept are shifted to fill the resulting gaps.
2537+
2538+
`inds` must be an iterator of sorted and unique integer indices.
2539+
See also [`deleteat!`](@ref).
2540+
2541+
!!! compat "Julia 1.7"
2542+
This function is available as of Julia 1.7.
2543+
2544+
# Examples
2545+
```jldoctest
2546+
julia> keepat!([6, 5, 4, 3, 2, 1], 1:2:5)
2547+
3-element Vector{Int64}:
2548+
6
2549+
4
2550+
2
2551+
```
2552+
"""
2553+
keepat!(a::Vector, inds) = _keepat!(a, inds)
2554+
2555+
"""
2556+
keepat!(a::Vector, m::AbstractVector{Bool})
2557+
2558+
The in-place version of logical indexing `a = a[m]`. That is, `keepat!(a, m)` on
2559+
vectors of equal length `a` and `m` will remove all elements from `a` for which
2560+
`m` at the corresponding index is `false`.
2561+
2562+
# Examples
2563+
```jldoctest
2564+
julia> a = [:a, :b, :c];
2565+
2566+
julia> keepat!(a, [true, false, true])
2567+
2-element Vector{Symbol}:
2568+
:a
2569+
:c
2570+
2571+
julia> a
2572+
2-element Vector{Symbol}:
2573+
:a
2574+
:c
2575+
```
2576+
"""
2577+
keepat!(a::Vector, m::AbstractVector{Bool}) = _keepat!(a, m)
2578+
25312579
# set-like operators for vectors
25322580
# These are moderately efficient, preserve order, and remove dupes.
25332581

base/bitarray.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1019,6 +1019,9 @@ function deleteat!(B::BitVector, inds)
10191019
return B
10201020
end
10211021

1022+
keepat!(B::BitVector, inds) = _keepat!(B, inds)
1023+
keepat!(B::BitVector, inds::AbstractVector{Bool}) = _keepat!(B, inds)
1024+
10221025
function splice!(B::BitVector, i::Integer)
10231026
i = Int(i)
10241027
n = length(B)

test/arrayops.jl

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1452,6 +1452,26 @@ end
14521452
@test isempty(eoa)
14531453
end
14541454

1455+
@testset "logical keepat!" begin
1456+
# Vector
1457+
a = Vector(1:10)
1458+
keepat!(a, [falses(5); trues(5)])
1459+
@test a == 6:10
1460+
@test_throws BoundsError keepat!(a, trues(1))
1461+
@test_throws BoundsError keepat!(a, trues(11))
1462+
1463+
# BitVector
1464+
ba = rand(10) .> 0.5
1465+
@test isa(ba, BitArray)
1466+
keepat!(ba, ba)
1467+
@test all(ba)
1468+
1469+
# empty array
1470+
ea = []
1471+
keepat!(ea, Bool[])
1472+
@test isempty(ea)
1473+
end
1474+
14551475
@testset "deleteat!" begin
14561476
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,
14571477
8:9, 9:10, 6:9, 7:10]

0 commit comments

Comments
 (0)