Skip to content
This repository has been archived by the owner on Dec 16, 2022. It is now read-only.

Commit

Permalink
Add logical indexing in deleteat!() (JuliaLang#20465)
Browse files Browse the repository at this point in the history
* Add logical indexing in deleteat!()

More consistent with what getindex() supports. This can allow
avoiding an allocation when the caller already has a boolean vector of
logical indices.

* Use to_indices() and @BoundsCheck

* Remove ineffective @BoundsCheck annotation
  • Loading branch information
nalimilan authored and ararslan committed Feb 11, 2017
1 parent 1eee998 commit 6974bde
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 2 deletions.
29 changes: 27 additions & 2 deletions base/array.jl
Original file line number Diff line number Diff line change
Expand Up @@ -794,7 +794,10 @@ end
deleteat!(a::Vector, inds)
Remove the items at the indices given by `inds`, and return the modified `a`.
Subsequent items are shifted to fill the resulting gap. `inds` must be sorted and unique.
Subsequent items are shifted to fill the resulting gap.
`inds` can be either an iterator or a collection of sorted and unique integer indices,
or a boolean vector of the same length as `a` with `true` indicating entries to delete.
```jldoctest
julia> deleteat!([6, 5, 4, 3, 2, 1], 1:2:5)
Expand All @@ -803,13 +806,22 @@ julia> deleteat!([6, 5, 4, 3, 2, 1], 1:2:5)
3
1
julia> deleteat!([6, 5, 4, 3, 2, 1], [true, false, true, false, true, false])
3-element Array{Int64,1}:
5
3
1
julia> deleteat!([6, 5, 4, 3, 2, 1], (2, 2))
ERROR: ArgumentError: indices must be unique and sorted
Stacktrace:
[1] deleteat!(::Array{Int64,1}, ::Tuple{Int64,Int64}) at ./array.jl:808
```
"""
function deleteat!(a::Vector, inds)
deleteat!(a::Vector, inds) = _deleteat!(a, inds)
deleteat!(a::Vector, inds::AbstractVector) = _deleteat!(a, to_indices(a, (inds,))[1])

function _deleteat!(a::Vector, inds)
n = length(a)
s = start(inds)
done(inds, s) && return a
Expand Down Expand Up @@ -838,6 +850,19 @@ function deleteat!(a::Vector, inds)
return a
end

# Simpler and more efficient version for logical indexing
function deleteat!(a::Vector, inds::AbstractVector{Bool})
n = length(a)
length(inds) == n || throw(BoundsError(a, inds))
p = 1
for (q, i) in enumerate(inds)
@inbounds a[p] = a[q]
p += !i
end
ccall(:jl_array_del_end, Void, (Any, UInt), a, n-p+1)
return a
end

const _default_splice = []

"""
Expand Down
12 changes: 12 additions & 0 deletions test/arrayops.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1067,8 +1067,17 @@ end
@testset "deleteat!" begin
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,
8:9, 9:10, 6:9, 7:10]
# integer indexing with AbstractArray
a = [1:10;]; acopy = copy(a)
@test deleteat!(a, idx) == [acopy[1:(first(idx)-1)]; acopy[(last(idx)+1):end]]

# integer indexing with non-AbstractArray iterable
a = [1:10;]; acopy = copy(a)
@test deleteat!(a, (i for i in idx)) == [acopy[1:(first(idx)-1)]; acopy[(last(idx)+1):end]]

# logical indexing
a = [1:10;]; acopy = copy(a)
@test deleteat!(a, map(i -> i in idx, 1:length(a))) == [acopy[1:(first(idx)-1)]; acopy[(last(idx)+1):end]]
end
a = [1:10;]
@test deleteat!(a, 11:10) == [1:10;]
Expand All @@ -1077,6 +1086,9 @@ end
@test_throws BoundsError deleteat!(a, [1,13])
@test_throws ArgumentError deleteat!(a, [5,3])
@test_throws BoundsError deleteat!(a, 5:20)
@test_throws BoundsError deleteat!(a, Bool[])
@test_throws BoundsError deleteat!(a, [true])
@test_throws BoundsError deleteat!(a, falses(11))
end

@testset "comprehensions" begin
Expand Down

0 comments on commit 6974bde

Please sign in to comment.