# Reverse multidimensional array

**URL:** <https://discourse.julialang.org/t/reverse-multidimensional-array/53777>\
**Category:** General Usage\
**Tags:** array, arrays\
**Created:** [January 22, 2021, 11:16am UTC](https://discourse.julialang.org/t/reverse-multidimensional-array/53777 "2021-01-22T11:16:09Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![roflmaostc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/roflmaostc/32/30123_2.png) [@roflmaostc](https://discourse.julialang.org/u/roflmaostc)\
**Post date:** [January 22, 2021, 11:16am UTC](https://discourse.julialang.org/t/reverse-multidimensional-array/53777/1 "2021-01-22T11:16:09Z")

</div>

Hey,

recently I wanted to reverse a multidimensional array. I didn’t find a built-in solution but only this post on [StackOverflow](https://stackoverflow.com/questions/27411401/julia-reverse-n-dimensional-arrays).

I was wondering what’s a proper implementation. I came up with the following. `reverse_2` is the the one from SO, but it’s horribly slow because it is copying everything for each reverse call again.  
`reverse_all` and `reverse_all_view` are basically the same, except the `@view`.

```julia
function reverse_all(arr::AbstractArray, dims=1:ndims(arr))
    return arr[reverse_all_indices(arr, dims)...]
end

function reverse_all_view(arr::AbstractArray, dims=1:ndims(arr))
    return @view arr[reverse_all_indices(arr, dims)...]
end

function reverse_all_indices(arr, dims=1:ndims(arr))
    out = []
    for i in 1:ndims(arr)
        push!(out, 1:size(arr)[i])
    end 
        
    for d in dims
        out[d] = size(arr)[d]:-1:1
    end
    
    return out 
end

function reverse_2(arr)
    for d = 1:ndims(arr)
        arr = reverse(arr, dims=d)
    end 
    return arr 
end

```

I often find myself writing code to construct the range expressions. Is there a better way? I’m aware of `CartesianIndices` but often I don’t find them easier.

```julia
julia> x = randn((1000, 12, 122, 140));

julia> @time y = reverse_all(x);
  0.988784 seconds (14 allocations: 1.527 GiB, 0.67% gc time)

julia> @time y_v = reverse_all_view(x);
  0.000014 seconds (12 allocations: 528 bytes)

julia> @time y_2 = reverse_2(x);
 32.074907 seconds (817.91 M allocations: 18.302 GiB, 7.29% gc time)

julia> y == y_2 == y_v
true

```

Thanks,

Felix

---

<div class="post-metadata">

**Author:** ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)\
**Post date:** [January 22, 2021, 11:32am UTC](https://discourse.julialang.org/t/reverse-multidimensional-array/53777/2 "2021-01-22T11:32:48Z")

</div>

`reverse(A; dims=3)` ?

Check a bit further down the page in the docs for `reverse`.

---

<div class="post-metadata">

**Author:** ![roflmaostc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/roflmaostc/32/30123_2.png) [@roflmaostc](https://discourse.julialang.org/u/roflmaostc)\
**Post date:** [January 22, 2021, 11:36am UTC](https://discourse.julialang.org/t/reverse-multidimensional-array/53777/3 "2021-01-22T11:36:51Z")

</div>

Hm, I don’t think that works.  
According to the [manual](https://docs.julialang.org/en/v1/base/arrays/#Base.reverse-Tuple%7BAbstractArray%7BT,1%7D%20where%20T%7D) it only reverses the dims dimension, not all dimensions.

That’s the reason to use the loop in `reverse_2`.

---

<div class="post-metadata">

**Author:** ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)\
**Post date:** [January 22, 2021, 11:44am UTC](https://discourse.julialang.org/t/reverse-multidimensional-array/53777/4 "2021-01-22T11:44:04Z")

</div>

Sure, you didnt say _all_ dimensions until further down than I read 🙂

With a matrix you can use `rot180` for that.

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [January 22, 2021, 12:38pm UTC](https://discourse.julialang.org/t/reverse-multidimensional-array/53777/5 "2021-01-22T12:38:11Z")

</div>

Julia 1.6’s `reverse` allows defining a tuple with several dimensions to reverse.  
Is this what you require:

```julia
julia> M=[i+j for i in -3:0, j in -1:1]
4×3 Matrix{Int64}:
 -4 -3 -2
 -3 -2 -1
 -2 -1 0
 -1 0 1

julia> reverse(M; dims=(1,2))
4×3 Matrix{Int64}:
  1 0 -1
  0 -1 -2
 -1 -2 -3
 -2 -3 -4

```

---

<div class="post-metadata">

**Author:** ![roflmaostc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/roflmaostc/32/30123_2.png) [@roflmaostc](https://discourse.julialang.org/u/roflmaostc)\
**Post date:** [January 22, 2021, 12:40pm UTC](https://discourse.julialang.org/t/reverse-multidimensional-array/53777/6 "2021-01-22T12:40:07Z")

</div>

Nice, sounds good!

I’ll need to check whether it creates a view und what’s the performance in comparison to above implementation.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [January 22, 2021, 1:32pm UTC](https://discourse.julialang.org/t/reverse-multidimensional-array/53777/7 "2021-01-22T13:32:33Z")

</div>

> [@roflmaostc](#):
>
> I’ll need to check whether it creates a view und what’s the performance in comparison to above implementation.

It doesn’t create a view, it makes a copy. You can also do `reverse!` to work in-place — this is the fastest option (that actually moves data) for large arrays.

Note also that the default is to reverse _all_ the dimensions, so if that is what you want then you can simply do `reverse(a)` or `reverse!(a)`.

```julia
julia> @btime reverse_all($x);
  1.152 s (14 allocations: 1.53 GiB)

julia> @btime reverse($x);
  1.171 s (3 allocations: 1.53 GiB)

julia> @btime reverse!($x);
  385.043 ms (0 allocations: 0 bytes)

```

PS. Implementing multidimensional `reverse!` is [fun and surprisingly compact](https://github.com/JuliaLang/julia/pull/37367), heavily using `CartesianIndices` tricks and recursion over the dimension.
