Is there a function to return a copy of an array with one or more elements removed? Or to splice in different elements into a copy of the array and return that?
I’ve been doing things like deleteat!(copy(arr), idxs)
, but since this is such a basic feature I wondered if I was missing an existing function to do it directly.
1 Like
getindex
(aka []
) and vcat
should do what you want, but if you want to provide indexes in the format used by eg deleteat!
you could use something like
julia> x = 1:5;
julia> x[setdiff(indices(x, 1), [2,3])]
3-element Array{Int64,1}:
1
4
5
The deleteat!(copy(
solution actually seems faster than this method though.
julia> y = rand(1:100, 100);
julia> del_sd(a, idx) = a[setdiff(indices(a, 1), idx)];
julia> del_cp(a, idx) = deleteat!(copy(a), idx);
julia> @btime del_cp(y, (2, 3, 43))
423.386 ns (1 allocation: 896 bytes)
97-element Array{Int64,1}:
90
88
30
41
16
⋮
22
18
78
17
julia> @btime del_sd(y, (2, 3, 43))
18.820 μs (25 allocations: 7.56 KiB)
97-element Array{Int64,1}:
90
88
30
41
16
⋮
22
18
78
17
julia>
(AFAICT, a getindex
+vcat
type solution would get kinda unwieldly unless the indices to be removed are contiguous, and not as readable as the deleteat!
version even for contiguous/single index cases.)
I’m ok with using the deleteat!(copy(arr), idxs)
method, that just seemed a roundabout way to do this so I wondered if there was an easier more obvious way that I was missing.
The logit of the _deleteat!
makes some assumptions which make it very efficient, so it may be worthwhile converting it to a non-modifying version.
What about
function deleteat(vec, idxs)
newlen = length(vec) - length(idxs)
vn = Vector{eltype(vec)}(newlen)
n=1
k=1
for idx in idxs
while n < idx
@inbounds vn[k]=vec[n]
k+=1
n+= 1
end
n+= 1
end
while k<=newlen
@inbounds vn[k] = vec[n]
k+=1
n+=1
end
vn
end
Insert error checking (idxs must be sorted and unique) if you want. Roughly as fast as memcopy when deleting few elements, and significantly faster than taking a copy and then copying vast portions around again.
Luckily, in julia there is no reason to compose Base functions in weird ways when you can just write a straight loop
1 Like