EndpointRanges.jl icon indicating copy to clipboard operation
EndpointRanges.jl copied to clipboard

Support for something like `imid` to access the middle.

Open roflmaostc opened this issue 4 years ago • 2 comments

Hey,

:cool: package! Is there any chance we can support something like imid (well, it's not a Endpoint, but MidPoint.jl would be maybe too much...)? I find it very useful to access the middle of the array easily. (Of course, it depends on the definition what's the mid point, maybe we could introduce imidl and imidr to clarify.)

I mean it already works somehow but the type is horribly long (and maybe much overhead for compiler/runtime?).

julia> using BenchmarkTools, EndpointRanges

julia> const imid = ibegin + (iend - ibegin + 1) ÷ 2   # (scroll to the right for the full type)
EndpointRanges.IndexFunction{EndpointRanges.var"#5#6"{EndpointRanges.IBegin, EndpointRanges.IndexFunction{EndpointRanges.var"#31#32"{EndpointRanges.IndexFunction{EndpointRanges.var"#7#8"{EndpointRanges.IndexFunction{EndpointRanges.var"#11#12"{EndpointRanges.IEnd, EndpointRanges.IBegin}}, Int64}}, Int64}}}}(EndpointRanges.var"#5#6"{EndpointRanges.IBegin, EndpointRanges.IndexFunction{EndpointRanges.var"#31#32"{EndpointRanges.IndexFunction{EndpointRanges.var"#7#8"{EndpointRanges.IndexFunction{EndpointRanges.var"#11#12"{EndpointRanges.IEnd, EndpointRanges.IBegin}}, Int64}}, Int64}}}(EndpointRanges.IBegin(), EndpointRanges.IndexFunction{EndpointRanges.var"#31#32"{EndpointRanges.IndexFunction{EndpointRanges.var"#7#8"{EndpointRanges.IndexFunction{EndpointRanges.var"#11#12"{EndpointRanges.IEnd, EndpointRanges.IBegin}}, Int64}}, Int64}}(EndpointRanges.var"#31#32"{EndpointRanges.IndexFunction{EndpointRanges.var"#7#8"{EndpointRanges.IndexFunction{EndpointRanges.var"#11#12"{EndpointRanges.IEnd, EndpointRanges.IBegin}}, Int64}}, Int64}(EndpointRanges.IndexFunction{EndpointRanges.var"#7#8"{EndpointRanges.IndexFunction{EndpointRanges.var"#11#12"{EndpointRanges.IEnd, EndpointRanges.IBegin}}, Int64}}(EndpointRanges.var"#7#8"{EndpointRanges.IndexFunction{EndpointRanges.var"#11#12"{EndpointRanges.IEnd, EndpointRanges.IBegin}}, Int64}(EndpointRanges.IndexFunction{EndpointRanges.var"#11#12"{EndpointRanges.IEnd, EndpointRanges.IBegin}}(EndpointRanges.var"#11#12"{EndpointRanges.IEnd, EndpointRanges.IBegin}(EndpointRanges.IEnd(), EndpointRanges.IBegin())), 1)), 2))))

julia> a = [1,2,3,4,5]
5-element Vector{Int64}:
 1
 2
 3
 4
 5

julia> a[imid]
3

julia> a = [1,2,3,4,5, 6]
6-element Vector{Int64}:
 1
 2
 3
 4
 5
 6

julia> a[imid]
4

I played with it and couldn't we include something like the following (I basically copied yours):

struct IMid <: Endpoint end 
const imid = IMid()
(::IMid)(r::AbstractRange) = first(r) + (last(r) - first(r) + 1) ÷ 2 
(::IMid)(b::Integer, e::Integer) = b + (e - b + 1) ÷ 2 
newindex(indA, i::IMid) = first(indA) + (last(indA) - first(indA) + 1) ÷ 2

MWE:

julia> a = [1,2,3,4, 5]
5-element Vector{Int64}:
 1
 2
 3
 4
 5

julia> a[imid]
3

julia> a[imid + 1]
4

julia> a = [1,2,3,4,5,6]
6-element Vector{Int64}:
 1
 2
 3
 4
 5
 6

julia> a[imid]
4

julia> a[imid-1]
3

julia> a[imid÷2]
2

If you think that would be an useful addition, I would be really happy opening a PR!

Thanks,

Felix

roflmaostc avatar Apr 27 '21 12:04 roflmaostc

Since Julia 1.4,

mymid(a, b) =  a + (b - a + 1) ÷ 2
A[mymid(begin, end)]

tpapp avatar Apr 27 '21 12:04 tpapp

That works yeah, but might be not as convenient as imid would be.

roflmaostc avatar Apr 27 '21 12:04 roflmaostc