How to create a reversed view that allows for growing arrays?

Forgive me for resurrecting an old thread, but being able to get an inverted view of an array is amazing to me as someone who is new to Julia but had to write a lot of code to get this kind of functionality in another language. However, I have a question. Suppose we have an array a and an inverted view of it in z.

a = [1:10;]
z = view(a, lastindex(a):-1:firstindex(a))
a[10] # 10
z[1]  # 10

So far, so good, but what if a gets a new element pushed on to it.

push!(a, 11)
a[11] # 11
z[1]  # 10 (but I want it to be 11)

Is there a good way to get the view z to track changes in the length of a?

I think this is the use case for a Reversed wrapper that constructs a range when getindex is called:

struct Reversed{T<:AbstractArray}
    A::T
end

Base.getindex(a::Reversed, i::Int) = a.A[end-i+1]

v = [1, 2, 3]
a = Reversed(v)
a[1] # 3
push!(v, 4)
a[1] # 4
2 Likes

I continue to be amazed by what Julia can do. Thanks for the answer, @simsurace. Thanks for moving the thread, @mbauman .

(For the curious, the OP of this thread was originally a reply in another thread.)

Just a minor note: you only want to iterate in reverse, rather than be able to index, the function Iterators.reverse will construct a reverse iterator for your vector, and will automatically accomodate changes to the underlying vector including adding new elements.

e.g.:

xs = rand(100)
sx = Iterators.reverse(xs)

xs[100] = 2
@assert first(sx) == 2  # true

push!(xs, 3)
@assert first(sx) == 3  # true
1 Like