Array range complement

后端 未结 2 917
执笔经年
执笔经年 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:28

    Directly overwriting [](i.e. getindex) is prone to break many indexing-related things in Base, but we can write an array wrapper to work around it. We only need to define the following three methods to get your specific test cases passed:

    immutable ComplementVector{T} <: AbstractArray{T,1}
        data::Vector{T}
    end
    Base.size(A:: ComplementVector) = size(A.data)
    Base.getindex(A:: ComplementVector, i::Integer) = i > 0 ? A.data[i] : A.data[setdiff(1:end, (-i))]
    Base.getindex(A:: ComplementVector, I::StepRange) = all(x->x>0, I) ? A.data[I] : A.data[setdiff(1:end, -I)]
    
    julia> a = ComplementVector([1:8...])
    
    julia> a[-1] == a[2:8]
    true
    
    julia> a[-(1:3)] == a[4:8]
    true
    
    julia> a[-end] == a[1:7]
    true
    

    If you would like to extend ComplementVector further more, please read the doc about Interfaces.

    Update:

    For safety sake, we'd better not extend AbstractArray as @Fengyang Wang suggested in the comment blow:

    immutable ComplementVector{T}
        data::Vector{T}
    end
    Base.endof(A::ComplementVector) = length(A.data)
    Base.getindex(A::ComplementVector, i::Integer) = i > 0 ? A.data[i] : A.data[setdiff(1:end, (-i))]
    Base.getindex(A::ComplementVector, I::OrdinalRange) = all(x->x>0, I) ? A.data[I] : A.data[setdiff(1:end, -I)]
    

提交回复
热议问题