Reversed Arrays

Is there a package that implements an array type where the index is reversed? I have an array that I would normally reverse the order but I don’t really want to incur an extra allocation cost or performance hit. So it would be nice to reference a[1] for the a[end] element and vice versa.

I thought it would be simple enough to create a custom array type but don’t want to reinvent any wheels…

Would this work?


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

julia> b = view(a, length(a):-1:1)
5-element view(::Array{Int64,1}, 5:-1:1) with eltype Int64:
 5
 4
 3
 2
 1

julia> b[end]
1
4 Likes

Thanks @yurivish. Very nice solution! Never thought of that being so simple :grinning:

BTW, indexing performance seems to suffer though:

julia> @benchmark getindex($a, 3)
BenchmarkTools.Trial: 
  memory estimate:  0 bytes
  allocs estimate:  0
  --------------
  minimum time:     1.755 ns (0.00% GC)
  median time:      1.762 ns (0.00% GC)
  mean time:        1.799 ns (0.00% GC)
  maximum time:     15.594 ns (0.00% GC)
  --------------
  samples:          10000
  evals/sample:     1000

julia> @benchmark getindex($b, 3)
BenchmarkTools.Trial: 
  memory estimate:  0 bytes
  allocs estimate:  0
  --------------
  minimum time:     15.855 ns (0.00% GC)
  median time:      16.240 ns (0.00% GC)
  mean time:        17.283 ns (0.00% GC)
  maximum time:     111.072 ns (0.00% GC)
  --------------
  samples:          10000
  evals/sample:     998

So I just did this for fun:

julia> struct ReverseVector{T} <: AbstractVector{T} 
           ar::Vector{T}
       end

julia> Base.getindex(v::ReverseVector, i::Integer) = getindex(v.ar, length(v.ar)-i+1)

julia> Base.size(v::ReverseVector) = size(v.ar)

julia> v = ReverseVector([1,2,3,4,5])
5-element ReverseVector{Int64}:
 5
 4
 3
 2
 1

julia> @benchmark getindex($v, 3)
BenchmarkTools.Trial: 
  memory estimate:  0 bytes
  allocs estimate:  0
  --------------
  minimum time:     2.102 ns (0.00% GC)
  median time:      2.451 ns (0.00% GC)
  mean time:        2.725 ns (0.00% GC)
  maximum time:     78.021 ns (0.00% GC)
  --------------
  samples:          10000
  evals/sample:     1000

4 Likes

FWIW, as your ReverseVector is immutable, you could store length(v.ar) as separate field to avoid a call everytime you index. Don’t know if/how much this really matters, though. Same for size(v.ar).