# Indexing an array of arbitrary dimension

**URL:** <https://discourse.julialang.org/t/indexing-an-array-of-arbitrary-dimension/130977>\
**Category:** New to Julia\
**Created:** [July 23, 2025, 3:09pm UTC](https://discourse.julialang.org/t/indexing-an-array-of-arbitrary-dimension/130977 "2025-07-23T15:09:43Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![prconlin](https://avatars.discourse-cdn.com/v4/letter/p/b19c9b/32.png) [@prconlin](https://discourse.julialang.org/u/prconlin)\
**Post date:** [July 23, 2025, 3:09pm UTC](https://discourse.julialang.org/t/indexing-an-array-of-arbitrary-dimension/130977/1 "2025-07-23T15:09:43Z")

</div>

I’m trying to write a function which returns a random index for each dimension of an array.  
It’s easy to do this if the dimensions of the array are known, but I want to abstract my function to work on arrays of arbitrary dimension.

The 1D case is very simple:

```julia
function rand_index_1D(a::AbstractVector)
    return rand(1:length(a))
end

```

Similarly, the 2D case:

```julia
function rand_index_2D(a::AbstractMatrix)
    i = rand(1:length(a[1,:]))
    j = rand(1:length(a[:,1]))
    return (i,j)
end

```

The trouble I’m having is writing a single function which will work for an array of any dimension. I’ve been trying to rewrite the 2D case into a loop, but I’m not sure how to slice the array correctly. What I have so far:

```julia
function rand_index_nD(a::AbstractArray)
    dims = size(a)
    nout = length(dims)
    v = Vector{Int64}(undef, nout)
    for n = 1:nout
    # assign v[n] somehow
    end
    return v
end

```

I suspect that Julia has a built-in function (eachslice, selectdim, etc) which would really help here, but I haven’t quite figured it out.

Any help would be appreciated,  
Thanks in advance.

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [July 23, 2025, 3:18pm UTC](https://discourse.julialang.org/t/indexing-an-array-of-arbitrary-dimension/130977/2 "2025-07-23T15:18:12Z")

</div>

I’d do: `rand.(axes(A))` or perhaps even `CartesianIndex(rand.(axes(A))`.

---

<div class="post-metadata">

**Author:** ![prconlin](https://avatars.discourse-cdn.com/v4/letter/p/b19c9b/32.png) [@prconlin](https://discourse.julialang.org/u/prconlin)\
**Post date:** [July 23, 2025, 3:50pm UTC](https://discourse.julialang.org/t/indexing-an-array-of-arbitrary-dimension/130977/3 "2025-07-23T15:50:36Z")

</div>

axes() is exactly what I needed. The following works for a (rectangular) array of any dimension:

```julia
function uniform_index(a::AbstractArray)
    foo = axes(a)
    return [rand(foo[i]) for i=1:length(foo)]
end

```

Unfortunately it does allocate seem to allocate, but that may just be an artifact of benchmarking in global scope. I’ll get back to you on that one.

Thanks again,

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [July 23, 2025, 3:53pm UTC](https://discourse.julialang.org/t/indexing-an-array-of-arbitrary-dimension/130977/4 "2025-07-23T15:53:21Z")

</div>

Yes, that will allocate because you’re explicitly creating an array with that comprehension. It really can be as simple as what I wrote:

```julia
uniform_index(a::AbstractArray) = rand.(axes(a))

```

---

<div class="post-metadata">

**Author:** ![eldee](https://avatars.discourse-cdn.com/v4/letter/e/b5a626/32.png) [@eldee](https://discourse.julialang.org/u/eldee)\
**Post date:** [July 23, 2025, 4:07pm UTC](https://discourse.julialang.org/t/indexing-an-array-of-arbitrary-dimension/130977/5 "2025-07-23T16:07:59Z")

</div>

If you want to avoid allocations, you could use an `NTuple`:

```julia
function uniform_index(a::AbstractArray{T, N}) where {T, N}
    return ntuple(Val(N)) do i
        rand(axes(a, i)) # safer than 1:size(a, i)
    end
end

using BenchmarkTools
A = rand(2, 3, 4)
@btime uniform_index($A)
# 16.016 ns (0 allocations: 0 bytes)
# (2, 3, 2)

```

A more elegant and equally performant (or perhaps a bit faster) approach is to use `CartesianIndices`:

```julia
@btime rand(CartesianIndices($A))
# 14.000 ns (0 allocations: 0 bytes)
# CartesianIndex(2, 3, 3)

```

Edit: A third option is

```julia
@btime map(rand, axes($A))
# 11.912 ns (0 allocations: 0 bytes)
# (1, 3, 1)

```

Edit2: Well, apparently I didn’t understand how `broadcast` works, since `mbauman`’s `rand.(axes(A))` was already non-allocating 🙂

```julia
@btime rand.(axes($A))
# 11.912 ns (0 allocations: 0 bytes)
# (1, 2, 1)
```
