I had not studied the insides of indexing before, but at first glance the following could work without interrupting too much:
immutable Not{T} idx::T end if :to_indices in names(Base) # 0.6 import Base: to_indices, uncolon, tail, _maybetail @inline to_indices(A, inds, I::Tuple{Not, Vararg{Any}}) = (setdiff(uncolon(inds, (:, tail(I)...)), I[1].idx), to_indices(A, _maybetail(inds), tail(I))...) else # 0.5 import Base: getindex, _getindex not_index(a::AbstractArray, I, i::Int) = I not_index(a::AbstractArray, I::Not, i::Int) = setdiff(indices(a, i), I.idx) getindex(a::AbstractArray, I::Not) = getindex(a, setdiff(linearindices(a), I.idx)) _getindex(::Base.LinearIndexing, a::AbstractArray, I::Vararg{Union{Real, AbstractArray, Colon, Not}}) = Base._getindex(Base.linearindexing(a), a, (not_index(a, idx, i) for (i,idx) in enumerate(I))...) end
For instance:
julia> a = reshape(1:9, (3, 3)) 3×3 Base.ReshapedArray{Int64,2,UnitRange{Int64},Tuple{}}: 1 4 7 2 5 8 3 6 9 julia> a[Not(2:8)] 2-element Array{Int64,1}: 1 9 julia> a[Not(1:2), :] 1×3 Array{Int64,2}: 3 6 9 julia> a[Not(end), end] 2-element Array{Int64,1}: 7 8
I did not like the performance and extensive testing was not carried out, so everything can be improved.
Edit:
I replaced the code with 0.6 with version of Matt B. from his github comment linked in the comments.
Due to its excellent design of array indexing implementations for 0.6, only one function needs to be extended to get indexing additions for getindex
, setindex
and view
, for example
julia> view(a, Not(2:8)) 2-element SubArray{Int64,1,UnitRange{Int64},Tuple{Array{Int64,1}},false}: 1 9 # collect because ranges are immutable julia> b = collect(a); b[Not(2), Not(2)] = 10; b 3×3 Array{Int64,2}: 10 4 10 2 5 8 10 6 10