Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC: Implementation of deleteat! (Fixes #5118) #5176

Merged
merged 2 commits into from
Jan 22, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ Library improvements

* `modpi` function ([#4799]).

* New function `deleteat!` deletes a specified index or indices and
returns the updated collection

Deprecated or removed
---------------------

Expand Down
174 changes: 118 additions & 56 deletions base/array.jl
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,65 @@ setindex!(A::Array, x, I::AbstractVector{Bool}, J::AbstractVector{Bool}) = setin
setindex!{T<:Real}(A::Array, x, I::AbstractVector{T}, J::AbstractVector{Bool}) = setindex!(A, x, I,find(J))
setindex!{T<:Real}(A::Array, x, I::AbstractVector{Bool}, J::AbstractVector{T}) = setindex!(A, x, find(I),J)

# efficiently grow an array

function _growat!(a::Vector, i::Integer, delta::Integer)
n = length(a)
if i < div(n,2)
_growat_beg!(a, i, delta)
else
_growat_end!(a, i, delta)
end
return a
end

function _growat_beg!(a::Vector, i::Integer, delta::Integer)
ccall(:jl_array_grow_beg, Void, (Any, Uint), a, delta)
@inbounds for k = 1:i-1
a[k] = a[k+delta]
end
return a
end

function _growat_end!(a::Vector, i::Integer, delta::Integer)
ccall(:jl_array_grow_end, Void, (Any, Uint), a, delta)
n = length(a)
@inbounds for k = n:-1:(i+delta)
a[k] = a[k-delta]
end
return a
end

# efficiently delete part of an array

function _deleteat!(a::Vector, i::Integer, delta::Integer)
n = length(a)
last = i+delta-1
if i-1 < n-last
_deleteat_beg!(a, i, delta)
else
_deleteat_end!(a, i, delta)
end
return a
end

function _deleteat_beg!(a::Vector, i::Integer, delta::Integer)
@inbounds for k = i+delta-1:-1:1+delta
a[k] = a[k-delta]
end
ccall(:jl_array_del_beg, Void, (Any, Uint), a, delta)
return a
end

function _deleteat_end!(a::Vector, i::Integer, delta::Integer)
n = length(a)
@inbounds for k = i:n-delta
a[k] = a[k+delta]
end
ccall(:jl_array_del_end, Void, (Any, Uint), a, delta)
return a
end

## Dequeue functionality ##

const _grow_none_errmsg =
Expand Down Expand Up @@ -754,56 +813,67 @@ function insert!{T}(a::Array{T,1}, i::Integer, item)
n = length(a)
if i > n
ccall(:jl_array_grow_end, Void, (Any, Uint), a, i-n)
elseif i > div(n,2)
ccall(:jl_array_grow_end, Void, (Any, Uint), a, 1)
for k=n+1:-1:i+1
a[k] = a[k-1]
end
else
ccall(:jl_array_grow_beg, Void, (Any, Uint), a, 1)
for k=1:(i-1)
a[k] = a[k+1]
end
_growat!(a, i, 1)
end
a[i] = item
return a
end

const _default_splice = []
function deleteat!(a::Vector, i::Integer)
if !(1 <= i <= length(a))
throw(BoundsError())
end
return _deleteat!(a, i, 1)
end

function splice!(a::Vector, i::Integer, ins::AbstractArray=_default_splice)
function deleteat!{T<:Integer}(a::Vector, r::Range1{T})
n = length(a)
if !(1 <= i <= n)
f = first(r)
l = last(r)
if !(1 <= f && l <= n)
throw(BoundsError())
end
return _deleteat!(a, f, length(r))
end

function deleteat!(a::Vector, inds)
n = length(a)
s = start(inds)
done(inds, s) && return a
(p, s) = next(inds, s)
q = p+1
while !done(inds, s)
(i,s) = next(inds, s)
if !(q <= i <= n)
i < q && error("indices must be unique and sorted")
throw(BoundsError())
end
while q < i
@inbounds a[p] = a[q]
p += 1; q += 1
end
q = i+1
end
while q <= n
@inbounds a[p] = a[q]
p += 1; q += 1
end
ccall(:jl_array_del_end, Void, (Any, Uint), a, n-p+1)
return a
end

const _default_splice = []

function splice!(a::Vector, i::Integer, ins::AbstractArray=_default_splice)
v = a[i]
m = length(ins)
if m == 0
if i < div(n,2)
for k = i:-1:2
a[k] = a[k-1]
end
ccall(:jl_array_del_beg, Void, (Any, Uint), a, 1)
else
for k = i:n-1
a[k] = a[k+1]
end
ccall(:jl_array_del_end, Void, (Any, Uint), a, 1)
end
_deleteat!(a, i, 1)
elseif m == 1
a[i] = ins[1]
else
if i < div(n,2)
ccall(:jl_array_grow_beg, Void, (Any, Uint), a, m-1)
for k = 1:i-1
a[k] = a[k+m-1]
end
else
ccall(:jl_array_grow_end, Void, (Any, Uint), a, m-1)
for k = n+m-1:-1:(i+1+(m-1))
a[k] = a[k-(m-1)]
end
end
_growat!(a, i, m-1)
for k = 1:m
a[i+k-1] = ins[k]
end
Expand All @@ -812,42 +882,34 @@ function splice!(a::Vector, i::Integer, ins::AbstractArray=_default_splice)
end

function splice!{T<:Integer}(a::Vector, r::Range1{T}, ins::AbstractArray=_default_splice)
v = a[r]
m = length(ins)
if m == 0
deleteat!(a, r)
return v
end

n = length(a)
f = first(r)
l = last(r)
if !(1 <= f && l <= n)
throw(BoundsError())
end
d = l-f+1
v = a[r]
m = length(ins)
d = length(r)

if m < d
delta = d - m
if f-1 < n-l
for k = l:-1:1+delta
a[k] = a[k-delta]
end
ccall(:jl_array_del_beg, Void, (Any, Uint), a, delta)
_deleteat_beg!(a, f, delta)
else
for k = f:n-delta
a[k] = a[k+delta]
end
ccall(:jl_array_del_end, Void, (Any, Uint), a, delta)
_deleteat_end!(a, l-delta+1, delta)
end
elseif m > d
delta = m - d
if f-1 < n-l
ccall(:jl_array_grow_beg, Void, (Any, Uint), a, delta)
for k = 1:f-1
a[k] = a[k+delta]
end
_growat_beg!(a, f, delta)
else
ccall(:jl_array_grow_end, Void, (Any, Uint), a, delta)
for k = n+delta:-1:(l+1+delta)
a[k] = a[k-delta]
end
_growat_end!(a, l+1, delta)
end
end

for k = 1:m
a[f+k-1] = ins[k]
end
Expand Down
99 changes: 91 additions & 8 deletions base/bitarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1049,12 +1049,7 @@ function insert!(B::BitVector, i::Integer, item)
B[i] = item
end

function splice!(B::BitVector, i::Integer)
n = length(B)
if !(1 <= i <= n)
throw(BoundsError())
end
v = B[i]
function _deleteat!(B::BitVector, i::Integer)

k, j = get_chunks_id(i)

Expand Down Expand Up @@ -1085,6 +1080,91 @@ function splice!(B::BitVector, i::Integer)

B.len -= 1

return B
end

function deleteat!(B::BitVector, i::Integer)
n = length(B)
if !(1 <= i <= n)
throw(BoundsError())
end

return _deleteat!(B, i)
end

function deleteat!(B::BitVector, r::Range1{Int})
n = length(B)
i_f = first(r)
i_l = last(r)
if !(1 <= i_f && i_l <= n)
throw(BoundsError())
end

Bc = B.chunks
new_l = length(B) - length(r)
delta_k = num_bit_chunks(new_l) - length(Bc)

copy_chunks(Bc, i_f, Bc, i_l+1, n-i_l)

if delta_k < 0
ccall(:jl_array_del_end, Void, (Any, Uint), Bc, -delta_k)
end

B.len = new_l

if new_l > 0
Bc[end] &= @_msk_end new_l
end

return B
end

function deleteat!(B::BitVector, inds)
n = new_l = length(B)
s = start(inds)
done(inds, s) && return B

Bc = B.chunks

(p, s) = next(inds, s)
q = p+1
new_l -= 1
while !done(inds, s)
(i,s) = next(inds, s)
if !(q <= i <= n)
i < q && error("indices must be unique and sorted")
throw(BoundsError())
end
new_l -= 1
if i > q
copy_chunks(Bc, p, Bc, q, i-q)
p += i-q
end
q = i+1
end

q <= n && copy_chunks(Bc, p, Bc, q, n-q+1)

delta_k = num_bit_chunks(new_l) - length(Bc)
delta_k < 0 && ccall(:jl_array_del_end, Void, (Any, Uint), Bc, -delta_k)

B.len = new_l

if new_l > 0
Bc[end] &= @_msk_end new_l
end

return B
end

function splice!(B::BitVector, i::Integer)
n = length(B)
if !(1 <= i <= n)
throw(BoundsError())
end

v = B[i] # TODO: change to a copy if/when subscripting becomes an ArrayView
_deleteat!(B, i)
return v
end
splice!(B::BitVector, i::Integer, ins::BitVector) = splice!(B, int(i):int(i), ins)
Expand All @@ -1103,9 +1183,12 @@ function splice!(B::BitVector, r::Range1{Int}, ins::BitVector = _default_bit_spl
throw(BoundsError())
end
if (i_f > n)
return append!(B, ins)
append!(B, ins)
return BitVector(0)
end

v = B[r] # TODO: change to a copy if/when subscripting becomes an ArrayView

Bc = B.chunks

lins = length(ins)
Expand All @@ -1129,7 +1212,7 @@ function splice!(B::BitVector, r::Range1{Int}, ins::BitVector = _default_bit_spl
Bc[end] &= @_msk_end new_l
end

return B
return v
end
splice!(B::BitVector, r::Range1{Int}, ins::AbstractVector{Bool}) = splice!(B, r, bitpack(ins))

Expand Down
1 change: 1 addition & 0 deletions base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -693,6 +693,7 @@ export
contains,
count,
delete!,
deleteat!,
eltype,
empty!,
endof,
Expand Down
10 changes: 10 additions & 0 deletions doc/stdlib/base.rst
Original file line number Diff line number Diff line change
Expand Up @@ -827,6 +827,16 @@ Dequeues

Insert an item at the given index.

.. function:: deleteat!(collection, index)

Remove the item at the given index, and return the modified collection. Subsequent items
are shifted to fill the resulting gap.

.. function:: deleteat!(collection, itr)

Remove the items at the indices given by `itr`, and return the modified collection. Subsequent
items are shifted to fill the resulting gap. `itr` must be sorted and unique.

.. function:: splice!(collection, index, [replacement]) -> item

Remove the item at the given index, and return the removed item. Subsequent items
Expand Down
Loading