Array range complement

后端 未结 2 1023
执笔经年
执笔经年 2021-01-18 05:41

Is there a way to overwrite [] to have complement of range in array?

julia> a=[1:8...]
8-element Array{Int64,1}:
 1
 2
 3
 4
 5
 6
 7
 8

jul         


        
2条回答
  •  长发绾君心
    2021-01-18 06:06

    I haven't looked into the internals of indexing before, but at a first glance, the following might work without breaking 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 example:

    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 didn't care for performance and also did no extensive testing, so things can certainly be improved.

    Edit:

    I replaced the code for 0.6 with Matt B. version from his github comment linked in the comments.

    Thanks to his great design of the array indexing implementation for 0.6, only a single function needs to be extended to get complement indexing for getindex, setindex and view, e.g.,

    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  
    

提交回复
热议问题