# How to use custom indices

**URL:** <https://discourse.julialang.org/t/how-to-use-custom-indices/9848>\
**Category:** General Usage\
**Tags:** indexing\
**Created:** [March 20, 2018, 10:12pm UTC](https://discourse.julialang.org/t/how-to-use-custom-indices/9848 "2018-03-20T22:12:25Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![leoll2](https://avatars.discourse-cdn.com/v4/letter/l/22d042/32.png) [@leoll2](https://discourse.julialang.org/u/leoll2)\
**Post date:** [March 20, 2018, 10:12pm UTC](https://discourse.julialang.org/t/how-to-use-custom-indices/9848/1 "2018-03-20T22:12:25Z")

</div>

Hello everyone, I’m having a hard time figuring out how to implement arrays with custom indices.  
I’ve read all the existing documentation out there, but it’s often poor and lacking of information, especially examples.  
I’m trying to implement a simple array (extending AbstractArray) with indices ranging between two custom values (‘lb’ and ‘ub’ below), which can also be negative numbers.

> struct MyType{T} \<: AbstractArray{T,1}  
> data::Array{T,1}  
> dim::Int #Number of components of ‘data’  
> lb::Int #lower bound of indices  
> ub::Int #Upper bound of indices  
> end

Now I’m really not sure how to redefine the array functions, in particular:

1. Shall I redefine show? Some say I shouldn’t, but why?
2. What about getindex() and setindex!()? No tutorial shows an example of their redefinition with custom indices, so I assume that they remain unchanged, but it seems strange.  
Maybe I should use ‘1+i-a.lb’ instead of ‘i’ as index of data?

Since I don’t know much about this, here’s the rest of my code until now, please suggest me what to change to make it work properly.

> MyType{T}(::Type{T}, n::Int, lb::Int = 0) = MyType(Array{T,1}(n), n, lb, lb+n-1);  
> MyType(n::Int) = MyType(Float64, n);  
> Base.size(a::MyType) = (a.dim,)  
> Base.IndexStyle(::Type{\<:MyType}) = IndexLinear()  
> Base.similar(a::MyType, ::Type{T}, d::Dims) where {T} = MyType(T, d[1])  
> Base.getindex(a::MyType, i::Int) = a.data[i]  
> Base.setindex!(a::MyType, v, i::Int) = (a.data[i] = v)  
> Base.indices(a::MyType) = map(URange, a.lb, a.ub)

Thanks in advance!

---

<div class="post-metadata">

**Author:** ![stillyslalom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stillyslalom/32/45687_2.png) [@stillyslalom](https://discourse.julialang.org/u/stillyslalom)\
**Post date:** [March 20, 2018, 10:32pm UTC](https://discourse.julialang.org/t/how-to-use-custom-indices/9848/2 "2018-03-20T22:32:41Z")

</div>

The work’s already been done in [OffsetArrays.jl](https://github.com/JuliaArrays/OffsetArrays.jl)

```julia
julia> using OffsetArrays

julia> w = OffsetArray(1:5, -2:2)
OffsetArrays.OffsetArray{Int64,1,UnitRange{Int64}} with indices -2:2:
 1
 2
 3
 4
 5

julia> w[0]
3

```

---

<div class="post-metadata">

**Author:** ![leoll2](https://avatars.discourse-cdn.com/v4/letter/l/22d042/32.png) [@leoll2](https://discourse.julialang.org/u/leoll2)\
**Post date:** [March 20, 2018, 11:05pm UTC](https://discourse.julialang.org/t/how-to-use-custom-indices/9848/3 "2018-03-20T23:05:58Z")

</div>

Well, this solves my specific problem, so I’m likely to accept this answer.  
Yet, I’d still like to know how to implement custom indices, because in the future I may work on something else that isn’t already solved (by OffsetArray).  
For example, how would you modify my code to make it work? Is it a simple task? Thanks again!

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [March 20, 2018, 11:29pm UTC](https://discourse.julialang.org/t/how-to-use-custom-indices/9848/4 "2018-03-20T23:29:57Z")

</div>

Your code looks very close, and I think that if you just do (as you suggest) overload getindex and setindex! to use `1 + i - a.lb` then your type will pretty much just work:

```julia
struct MyType{T} <: AbstractArray{T,1}
    data::Array{T,1}
    dim::Int #Number of components of ‘data’
    lb::Int #lower bound of indices
    ub::Int #Upper bound of indices
end

MyType{T}(::Type{T}, n::Int, lb::Int = 0) = MyType(Array{T,1}(n), n, lb, lb+n-1);
Base.size(a::MyType) = (a.dim,)
Base.IndexStyle(::Type{<:MyType}) = IndexLinear()
Base.similar(a::MyType, ::Type{T}, d::Dims{1}) where {T} = MyType(T, d[1])
Base.getindex(a::MyType, i::Int) = a.data[1 + i - a.lb]
Base.setindex!(a::MyType, v, i::Int) = (a.data[1 + i - a.lb] = v)
Base.indices(a::MyType) = (a.lb:a.ub,)

```

Usage:

```julia
julia> m = MyType(Float64, 5, -2)
MyType{Float64} with indices -2:2:
 0.0
 0.0
 0.0
 0.0
 0.0

julia> m .= 0
MyType{Float64} with indices -2:2:
 0.0
 0.0
 0.0
 0.0
 0.0

julia> m[0] = 5
5

julia> m
MyType{Float64} with indices -2:2:
 0.0
 0.0
 5.0
 0.0
 0.0

julia> sum(m)
5.0

```

I also made a couple of very minor changes:

- restricted your `similar` method to `Dims{1}`, since your type is one-dimensional and it doesn’t make sense to call `similar(MyType, T, dims)` with a multi-dimensional `dims`
- simplified Base.indices to just `a.lb:a.ub`

---

<div class="post-metadata">

**Author:** ![tbeason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tbeason/32/15898_2.png) [@tbeason](https://discourse.julialang.org/u/tbeason)\
**Post date:** [March 20, 2018, 11:32pm UTC](https://discourse.julialang.org/t/how-to-use-custom-indices/9848/5 "2018-03-20T23:32:14Z")

</div>

I think the best answer to this would be to look at the OffsetArray source code and go from there. As far as I know, you do need to define `getindex` and `setindex!` methods for your array type, both for integer indexing and cartesian indexing (`Vararg{Int,N}`).
