# Missing \`deleteat!\` method for SparseVector

**URL:** https://discourse.julialang.org/t/missing-deleteat-method-for-sparsevector/69370
**Category:** General Usage
**Tags:** sparse
**Created:** [October 7, 2021, 1:20pm UTC](https://discourse.julialang.org/t/missing-deleteat-method-for-sparsevector/69370 "2021-10-07T13:20:37Z")
**Posts on this page:** 9
**Page:** 1

<div class="post-metadata">

### Author: ![lrnv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lrnv/32/19373_2.png) [@lrnv](https://discourse.julialang.org/u/lrnv)
#### Post date: [October 7, 2021, 1:20pm UTC](https://discourse.julialang.org/t/missing-deleteat-method-for-sparsevector/69370/1 "2021-10-07T13:20:37Z")

</div>

Hey,

I came across the following missing method:

```julia
deleteat!(::SparseVector{Float64, Int64}, ::Int64)

```

Indeed,

```julia
julia> x = sparse([0,1,0])
3-element SparseVector{Int64, Int64} with 1 stored entry:
  [2] = 1

julia> deleteat!(x,1)
ERROR: MethodError: no method matching deleteat!(::SparseVector{Int64, Int64}, ::Int64)
Closest candidates are:
  deleteat!(::Vector{T} where T, ::Integer) at array.jl:1343
  deleteat!(::Vector{T} where T, ::Any) at array.jl:1380
  deleteat!(::BitVector, ::Integer) at bitarray.jl:949
  ...
Stacktrace:
 [1] top-level scope
   @ REPL[53]:1

julia> deleteat!(x,2)
ERROR: MethodError: no method matching deleteat!(::SparseVector{Int64, Int64}, ::Int64)
Closest candidates are:
  deleteat!(::Vector{T} where T, ::Integer) at array.jl:1343
  deleteat!(::Vector{T} where T, ::Any) at array.jl:1380
  deleteat!(::BitVector, ::Integer) at bitarray.jl:949
  ...
Stacktrace:
 [1] top-level scope
   @ REPL[54]:1

julia> x = Vector(x)
3-element Vector{Int64}:
 0
 1
 0

julia> deleteat!(x,2)
2-element Vector{Int64}:
 0
 0

julia> 

```

To fix it, I added to my script the follwoing:

```julia
function Base.deleteat!(x::SparseVector{T,I},idx) where {T,I}
    x = vcat(x[begin:(idx-1)],x[(idx+1):end])
end

```

But i’m sure its suboptimal. What should i do ?

---

<div class="post-metadata">

### Author: ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)
#### Post date: [October 7, 2021, 1:28pm UTC](https://discourse.julialang.org/t/missing-deleteat-method-for-sparsevector/69370/2 "2021-10-07T13:28:25Z")

</div>

Maybe this?

```julia
julia> function deleteat!(x::SparseVector,ind) 
           ind_sparse = findfirst(isequal(ind),x.nzind)
           deleteat!(x.nzval,ind_sparse)
           deleteat!(x.nzind,ind_sparse)
           return x
       end
deleteat! (generic function with 9 methods)

julia> x = sparse([0,1,0,1,0])
5-element SparseVector{Int64, Int64} with 2 stored entries:
  [2] = 1
  [4] = 1

julia> deleteat!(x,4)
5-element SparseVector{Int64, Int64} with 1 stored entry:
  [2] = 1

```

(maybe `searchsortedfirst` should be used instead of `findfirst` there)

---

<div class="post-metadata">

### Author: ![lrnv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lrnv/32/19373_2.png) [@lrnv](https://discourse.julialang.org/u/lrnv)
#### Post date: [October 7, 2021, 1:38pm UTC](https://discourse.julialang.org/t/missing-deleteat-method-for-sparsevector/69370/3 "2021-10-07T13:38:00Z")

</div>

Well, as your example shows, and I do not get why, your array still has length 5 which is not correct. You basically just reproduced :

```julia
x[ind] .= zero(eltype(x))

```

---

<div class="post-metadata">

### Author: ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)
#### Post date: [October 7, 2021, 1:43pm UTC](https://discourse.julialang.org/t/missing-deleteat-method-for-sparsevector/69370/4 "2021-10-07T13:43:37Z")

</div>

Ah, then this should do the trick:

```julia
julia> using Setfield

julia> function deleteat!(x::SparseVector,ind) 
           ind_sparse = findfirst(isequal(ind),x.nzind)
           deleteat!(x.nzval,ind_sparse)
           deleteat!(x.nzind,ind_sparse)
           @set! x.n -= 1
           return x
       end
deleteat! (generic function with 9 methods)

julia> x = sparse([0,1,0,1,0])
5-element SparseVector{Int64, Int64} with 2 stored entries:
  [2] = 1
  [4] = 1

julia> x = deleteat!(x,4)
4-element SparseVector{Int64, Int64} with 1 stored entry:
  [2] = 1

```

But be careful that this does not really mutates the original array (because the length is immutable). You have to do `x = deletat!(x)`.

---

<div class="post-metadata">

### Author: ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)
#### Post date: [October 7, 2021, 1:47pm UTC](https://discourse.julialang.org/t/missing-deleteat-method-for-sparsevector/69370/5 "2021-10-07T13:47:27Z")

</div>

> [@lrnv](#):
>
> `x[ind] .= zero(eltype(x))`

No, that is not the same, because the lengths of the supporting arrays (`nzind` and `nzval`) are changed in my example.

---

<div class="post-metadata">

### Author: ![lrnv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lrnv/32/19373_2.png) [@lrnv](https://discourse.julialang.org/u/lrnv)
#### Post date: [October 7, 2021, 1:48pm UTC](https://discourse.julialang.org/t/missing-deleteat-method-for-sparsevector/69370/6 "2021-10-07T13:48:15Z")

</div>

Indeed it was not the same.

Thanks for the `Setfield` showcase, I did not know about this package.

---

<div class="post-metadata">

### Author: ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)
#### Post date: [October 7, 2021, 1:56pm UTC](https://discourse.julialang.org/t/missing-deleteat-method-for-sparsevector/69370/7 "2021-10-07T13:56:47Z")

</div>

It is actually not needed there. It is the same as doing this (which highlights the fact that you have to be careful with the fact that a new array was defined):

```julia
julia> import Base:deleteat!

julia> using SparseArrays

julia> function deleteat!(x::SparseVector,ind) 
           ind_sparse = findfirst(isequal(ind),x.nzind)
           deleteat!(x.nzval,ind_sparse)
           deleteat!(x.nzind,ind_sparse)
           return SparseVector(x.n-1,x.nzind,x.nzval)
       end
deleteat! (generic function with 9 methods)

julia> x = sparse([0,1,0,1,0])
5-element SparseVector{Int64, Int64} with 2 stored entries:
  [2] = 1
  [4] = 1

julia> x = deleteat!(x,4)
4-element SparseVector{Int64, Int64} with 1 stored entry:
  [2] = 1

```

---

<div class="post-metadata">

### Author: ![lrnv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lrnv/32/19373_2.png) [@lrnv](https://discourse.julialang.org/u/lrnv)
#### Post date: [October 7, 2021, 2:12pm UTC](https://discourse.julialang.org/t/missing-deleteat-method-for-sparsevector/69370/8 "2021-10-07T14:12:23Z")

</div>

> [@lmiq](#):
>
> ```julia
> function deleteat!(x::SparseVector,ind) 
> ind_sparse = findfirst(isequal(ind),x.nzind)
> deleteat!(x.nzval,ind_sparse)
> deleteat!(x.nzind,ind_sparse)
> return SparseVector(x.n-1,x.nzind,x.nzval)
> end
> 
> ```

To obtain the same interface, can i do instead :

```julia
function deleteat(x::SparseVector,ind) 
    ind_sparse = findfirst(isequal(ind),x.nzind)
    deleteat!(x.nzval,ind_sparse)
    deleteat!(x.nzind,ind_sparse)
    return SparseVector(x.n-1,x.nzind,x.nzval)
end
function deleteat!(x::Sparsevector,ind)
    x = deleteat(x,ind)
end

```

So that whatever the vector, calling `deleteat!()` has the same behavior ? Of course, this masks the fact that the vector has to be redefined.

---

<div class="post-metadata">

### Author: ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)
#### Post date: [October 7, 2021, 2:17pm UTC](https://discourse.julialang.org/t/missing-deleteat-method-for-sparsevector/69370/9 "2021-10-07T14:17:06Z")

</div>

No, that will be the same. You cannot really have the same interface, because the `SparseVector` is immutable (it contains mutable fields, but the `n` field is not mutable). You have to return `x` and reassign it on return, in any case. (that probably explains why there is no `deleteat!` defined by default for sparse vectors).
