# Operations on Arrays of CartesianIndex

**URL:** <https://discourse.julialang.org/t/operations-on-arrays-of-cartesianindex/58827>\
**Category:** General Usage\
**Tags:** indexing, cartesianindices, splitapplycombine\
**Created:** [April 8, 2021, 1:30pm UTC](https://discourse.julialang.org/t/operations-on-arrays-of-cartesianindex/58827 "2021-04-08T13:30:39Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![ethomag](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ethomag/32/421_2.png) [@ethomag](https://discourse.julialang.org/u/ethomag)\
**Post date:** [April 8, 2021, 1:30pm UTC](https://discourse.julialang.org/t/operations-on-arrays-of-cartesianindex/58827/1 "2021-04-08T13:30:39Z")

</div>

I came across a problem that I found surprisingly hard, given Julias excellent support for indexing multidimensional `Array`s.  
I lilke to apply some function along one axis on parts of an `Array`. The parts are defined by some predicate:

```julia
julia> size(A)
(1272, 32, 14, 120)
julia> ix = findall(predicate, A)
8904-element Vector{CartesianIndex{4}}:
 CartesianIndex(1, 1, 5, 17)
 CartesianIndex(5, 1, 5, 17)
 ...

```

Now I want to find the triplets of the three final indices for which the predicate is true. Note that these triplets are not necessarily permutations of single indices, so that filtering the indices out one by one would give me to many.

```julia
julia> ix2 = unique([i[2] for i in ix]);
julia> ix3 = unique([i[3] for i in ix]);
julia> ix4 = unique([i[4] for i in ix]);
julia> prod(length.([ix2,ix3,ix4]))
540

```

I solved it by doing this:

```julia
Base.getindex(index::CartesianIndex, r::UnitRange{Int}) = index.I[r]

```

Then, I can do:

```julia
ix234 = unique(getindex.(ix, [2:4]))
30-element Vector{Tuple{Int64, Int64, Int64}}:
 (1, 5, 17)
 (2, 5, 17)
 ...
for (ix2, ix3, ix4) in ix234
   ix1 = getindex.(filter(x -> x[2:4] == (ix2, ix3, ix4), ix), 1)
   f(A[ix1, ix2, ix3, ix4])
end

```

My guess is that this is not an uncommon task, e.g. having one `Array` describing the contents of another `Array` with the same dimensions.  
I suspect there is a more elegant way to accomplish this, but I can’t figure out how. Also, before posting I searched through other posts dealing with `CartesianIndex` and I understood that the Julia crew wants to avoid encouraging users to broadcast over the components of `CartesianIndex`. Does this solution violate this ?

So, my question is: Is this something that should go into Base ? Maybe accompanied with (which I also found handy):

```julia
Base.getindex(index::CartesianIndex, t::NTuple{N, Int}) where {N} = CartesianIndex([index[i] for i in t]...)
Base.lastindex(index::CartesianIndex) = lastindex(index.I)

```

---

<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:** [April 8, 2021, 10:54pm UTC](https://discourse.julialang.org/t/operations-on-arrays-of-cartesianindex/58827/2 "2021-04-08T22:54:38Z")

</div>

I think what you’re writing here is a group-by operation, which several packages support, in slightly different ways, see [#32331](https://github.com/JuliaLang/julia/issues/32331) for discussion.

```julia
julia> A = reshape(1:12, 3,2,2,1);

julia> ix = findall(iseven, A)
6-element Vector{CartesianIndex{4}}:
 CartesianIndex(2, 1, 1, 1)
 CartesianIndex(1, 2, 1, 1)
 CartesianIndex(3, 2, 1, 1)
 CartesianIndex(2, 1, 2, 1)
 CartesianIndex(1, 2, 2, 1)
 CartesianIndex(3, 2, 2, 1)

julia> unique(I -> (I[2], I[3]), ix)
4-element Vector{CartesianIndex{4}}:
 CartesianIndex(2, 1, 1, 1)
 CartesianIndex(1, 2, 1, 1)
 CartesianIndex(2, 1, 2, 1)
 CartesianIndex(1, 2, 2, 1)

julia> using SplitApplyCombine

julia> group(I -> I.I[2:end], ix).values
4-element Vector{Vector{CartesianIndex{4}}}:
 [CartesianIndex(2, 1, 1, 1)]
 [CartesianIndex(1, 2, 1, 1), CartesianIndex(3, 2, 1, 1)]
 [CartesianIndex(2, 1, 2, 1)]
 [CartesianIndex(1, 2, 2, 1), CartesianIndex(3, 2, 2, 1)]

```

---

<div class="post-metadata">

**Author:** ![ethomag](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ethomag/32/421_2.png) [@ethomag](https://discourse.julialang.org/u/ethomag)\
**Post date:** [April 9, 2021, 5:01am UTC](https://discourse.julialang.org/t/operations-on-arrays-of-cartesianindex/58827/3 "2021-04-09T05:01:06Z")

</div>

Thanks @mcabbot. I didn’t know of that form of `unique` invocation.
