Slice, ignoring out of bounds

I want to slice an array ignoring any out-of-bounds indices. Is there a preferred way to do this?

My solution

safeslice(a, ixs) = a[filter(i -> checkbounds(Bool, a, i), ixs)]
julia> safeslice([10,20,30], -4:2)
2-element Vector{Int64}:
 10
 20

You should consider something using intersect on the CartesianIndices

julia> a = zeros(3,4,5);

julia> a[intersect(CartesianIndices(a),CartesianIndices((3:5,3:5,3:5)))]
1×2×3 Array{Float64, 3}:
[:, :, 1] =
 0.0  0.0

[:, :, 2] =
 0.0  0.0

[:, :, 3] =
 0.0  0.0

This will figure out the valid indices up front, so won’t have to check each index individually. In this way, it should be much more efficient (if that matters to your case). It should also make it safe to use with @inbounds, which may be necessary to get the full efficiency out of it.

You can also look into the get function, if you want some other value returned on the invalid indices (but that does not appear to be your case here).

2 Likes
(partialgetindices(a, ixs::T) where T <: AbstractArray{CartesianIndex{S}} where S) =
       a[intersect(CartesianIndices(a), ixs)]

julia> partialgetindices([10,20,30], CartesianIndex.([0,1,2]))
2-element Vector{Int64}:
 10
 20

Here’s a version I threw together, based on intersecting the axes rather than CartesianIndices but otherwise very similar. By using to_indices, this one supports : and ::Int indices as well. It doesn’t drop ::Int slices like normal getindex does, since it needs to be able to drop if the value is out of range. You might find it slightly more ergonomic.

julia> partialgetindices(a::AbstractArray{<:Any,N}, ixs::Vararg{Any,N}) where N = a[intersect.(axes(a), to_indices(a, ixs))...]
partialgetindices (generic function with 1 method)

julia> a = zeros(3,4,5);

julia> partialgetindices(a,-10:2,:,1)
2×4×1 Array{Float64, 3}:
[:, :, 1] =
 0.0  0.0  0.0  0.0
 0.0  0.0  0.0  0.0
2 Likes