# Enumerate multi dimensional array

**URL:** <https://discourse.julialang.org/t/enumerate-multi-dimensional-array/48877>\
**Category:** New to Julia\
**Tags:** arrays\
**Created:** [October 23, 2020, 11:51am UTC](https://discourse.julialang.org/t/enumerate-multi-dimensional-array/48877 "2020-10-23T11:51:59Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![Torkel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/torkel/32/5030_2.png) [@Torkel](https://discourse.julialang.org/u/Torkel)\
**Post date:** [October 23, 2020, 11:51am UTC](https://discourse.julialang.org/t/enumerate-multi-dimensional-array/48877/1 "2020-10-23T11:51:59Z")

</div>

Is there a way to use enumerate of a multi-dimensional array, something like:

```julia
function new_matrix(matrix)
    new_matrix = copy(matrix)
    for (i,j,element) in enumerate(matrix)
        new_matrix[i,j] = i*j*matrix[i,j]
    end
    return new_matrix
end

```

?

---

<div class="post-metadata">

**Author:** ![oheil](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oheil/32/220745_2.png) [@oheil](https://discourse.julialang.org/u/oheil)\
**Post date:** [October 23, 2020, 12:02pm UTC](https://discourse.julialang.org/t/enumerate-multi-dimensional-array/48877/2 "2020-10-23T12:02:50Z")

</div>

You may look for  
`axes(matrix)`

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [October 23, 2020, 12:30pm UTC](https://discourse.julialang.org/t/enumerate-multi-dimensional-array/48877/3 "2020-10-23T12:30:32Z")

</div>

`axes` doesn’t include the value, unlike `enumerate`. And actually, it’s not `enumerate` you want, even for one-dimensional vectors. You should use `pairs`, since enumerate always starts counting at 1 no matter what sort of array you have (even 0-indexed arrays).

```julia
julia> a = randn(3,2)
3×2 Array{Float64,2}:
  0.446886 0.168215
 -0.0590402 1.89755
  0.0420936 -1.62462

julia> for (ind, val) in pairs(a)
       println(ind, ": ", val)
       end
CartesianIndex(1, 1): 0.4468857733868482
CartesianIndex(2, 1): -0.0590401519075785
CartesianIndex(3, 1): 0.04209357154257153
CartesianIndex(1, 2): 0.16821454509635914
CartesianIndex(2, 2): 1.8975549461332841
CartesianIndex(3, 2): -1.624623544140236

```

You can get `(i, j)` from calling `Tuple(ind)`, but you should rather use the cartesian index directly:

```julia
function new_matrix(matrix)
    new_matrix = copy(matrix)
    for (ind, element) in pairs(matrix)
        (i, j) = Tuple(ind)
        new_matrix[ind] = i * j * matrix[ind] # or ind[1]*ind[2] * matrix[ind]
    end
    return new_matrix
end

```

---

<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:** [October 23, 2020, 12:32pm UTC](https://discourse.julialang.org/t/enumerate-multi-dimensional-array/48877/4 "2020-10-23T12:32:29Z")

</div>

Maybe:

```julia
function new_matrix(matrix::AbstractMatrix)
    new_matrix = similar(matrix)
    for ij in CartesianIndices(matrix)
        new_matrix[ij] = ij[1]*ij[2]*matrix[ij]
    end
    return new_matrix
end

```

You could do `for (ij, val) in zip(CartesianIndices(matrix), matrix)` to be closer to `enumerate`, but it’s probably not worth `enumerate` is mainly useful for non-indexable collections. _Update:_ there is also `pairs`, as mentioned by @DNF [above](https://discourse.julialang.org/t/enumerate-multi-dimensional-array/48877/3).

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [October 23, 2020, 12:38pm UTC](https://discourse.julialang.org/t/enumerate-multi-dimensional-array/48877/5 "2020-10-23T12:38:54Z")

</div>

> [@DNF](#):
>
> ```julia
> function new_matrix(matrix)
> new_matrix = copy(matrix)
> for (ind, element) in pairs(matrix)
> (i, j) = Tuple(ind)
> new_matrix[ind] = i * j * matrix[ind] # or ind[1]*ind[2] * matrix[ind]
> end
> return new_matrix
> end
> 
> ```

BTW, there are some not-so-nice things here. Don’t give your output matrix the same name as the function: `new_matrix`, that’s probably a bad idea. And a tip: use `similar(matrix)` instead of `copy(matrix)`, it can be a _lot_ faster.

Here’s some code that actually uses the `pairs` feature better:

```julia
function new_matrix(matrix)
    matrix_ = similar(matrix)
    for (ind, element) in pairs(matrix)
        matrix_[ind] = ind[1] * ind[2] * element 
    end
    return matrix_
end

```

And this code works for all array dimensionalities from 0 to N

```julia
function new_arr(arr)
    arr_ = similar(arr)
    for (ind, element) in pairs(arr)
        arr_[ind] = prod(Tuple(ind)) * element
    end
    return arr_
end

```

---

<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:** [October 23, 2020, 12:56pm UTC](https://discourse.julialang.org/t/enumerate-multi-dimensional-array/48877/6 "2020-10-23T12:56:58Z")

</div>

> [@stevengj](#):
>
> `ij[1]*ij[2]*matrix[ij]`

Even shorter:

```julia
new_matrix(matrix) = [ij[1]*ij[2]*matrix[ij] for ij in CartesianIndices(matrix)]

```

which has the advantage of more flexibly computing the return type. (e.g. if you have a `Matrix{Bool}` it will return a `Matrix{Int}` thanks to promotion.)

---

<div class="post-metadata">

**Author:** ![mcabbott](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mcabbott/32/6603_2.png) [@mcabbott](https://discourse.julialang.org/u/mcabbott)\
**Post date:** [October 23, 2020, 1:03pm UTC](https://discourse.julialang.org/t/enumerate-multi-dimensional-array/48877/7 "2020-10-23T13:03:30Z")

</div>

Surprisingly `pairs` can’t be used with `map`, otherwise this might be another neat way:

```julia
julia> map(enumerate(rand(Bool, 2,10))) do (i,v)
         i * v
       end
2×10 Matrix{Int64}:
 0 0 5 0 9 11 0 0 0 0
 2 0 0 8 10 0 14 0 18 0

julia> map(pairs(rand(Bool, 2,10))) do (i,v)
         prod(i.I) * v
       end
ERROR: map is not defined on dictionaries

```

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [October 23, 2020, 1:04pm UTC](https://discourse.julialang.org/t/enumerate-multi-dimensional-array/48877/8 "2020-10-23T13:04:51Z")

</div>

> [@stevengj](#):
>
> ```julia
> [ij[1]*ij[2]*matrix[ij] for ij in CartesianIndices(matrix)]
> 
> ```

And for arbitrary dimensions:

```julia
new_arr(x) = [prod(Tuple(ind)) * element for (ind, element) in pairs(x)]

```

---

<div class="post-metadata">

**Author:** ![Torkel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/torkel/32/5030_2.png) [@Torkel](https://discourse.julialang.org/u/Torkel)\
**Post date:** [October 23, 2020, 1:15pm UTC](https://discourse.julialang.org/t/enumerate-multi-dimensional-array/48877/9 "2020-10-23T13:15:17Z")

</div>

Thanks everyone, this is really helpful!

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [October 23, 2020, 2:08pm UTC](https://discourse.julialang.org/t/enumerate-multi-dimensional-array/48877/10 "2020-10-23T14:08:04Z")

</div>

It is indeed weird that `map` deliberately does not support `pairs`. Last year I asked a question about this in a slightly different context of `NamedTuple`s: [Map over namedtuple keys and values: confusing error](https://discourse.julialang.org/t/map-over-namedtuple-keys-and-values-confusing-error/26866).

---

<div class="post-metadata">

**Author:** ![mcabbott](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mcabbott/32/6603_2.png) [@mcabbott](https://discourse.julialang.org/u/mcabbott)\
**Post date:** [October 23, 2020, 3:59pm UTC](https://discourse.julialang.org/t/enumerate-multi-dimensional-array/48877/11 "2020-10-23T15:59:32Z")

</div>

Thanks, I hadn’t seen the thread from last year. I made [https://github.com/JuliaLang/julia/pull/38150](https://github.com/JuliaLang/julia/pull/38150) and we will see what people think.

---

<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:** [December 25, 2021, 10:37pm UTC](https://discourse.julialang.org/t/enumerate-multi-dimensional-array/48877/12 "2021-12-25T22:37:15Z")

</div>

Looking at the code above and without taking credit from the authors of all the clever solutions, for the lazy the fast and intuitive `TensorCast` is a friend, it trivially enumerates and provides elementwise access:

```julia
# N-dimensional very fast solution by @DNF
function new_arr(arr)
    arr_ = similar(arr)
    for (ind, element) in pairs(arr)
        arr_[ind] = prod(Tuple(ind)) * element
    end
    return arr_
end

a = rand(4,3,2)
b = new_arr(a)

# Lazy solution using TensorCast (not as fast but versatile and easy to remember):
using TensorCast
@cast c[i,j,k] := i*j*k*a[i,j,k]

c == b # true

```

Merry Christmas! 🎄
