 # How to use CartesianIndices to replace two nested loops

I’m trying to make a scatter plot where the x,y pairs form a (not necessarily rectangular) grid. The color of each point depends in a rather complicated way on the index of the point. Given two vectors, a1 and a2, my points are `n*a1+m*a2`, where n and m each span some integer range.

I made this work by using two nested loops and computing a single index for each point, but I can’t help but think that `CartesianIndices` is perfect for this use case. Despite spending a couple of hours, I couldn’t figure out how to use `CartesianIndices`. Here’s a minimal working example.

``````using Plots
nx, ny = 4,5
x = zeros(nx*ny)
y = zeros(nx*ny)
c = zeros(nx*ny)
a1, a2 = [1.1,.5], [-.2,1.0]
b = hcat(a1,a2)
for i in 0:nx-1
for j in 0:ny-1
idx = j+i*ny+1
x[idx],y[idx] = b*[i,j]
c[idx] = mod(i,7)/7+mod(j,3)/3
end
end
scatter(x,y,marker_z=c,colormap=:thermal)
``````

While this is a passable solution, it seems rather like I’m still writing in Fortran…any suggestions on how to make this more Julian?

One way:

``````CI = CartesianIndices((0:ny-1, 0:nx-1))
LI = LinearIndices(CI)
for (I, L) in zip(CI, LI)
x[L], y[L] = b * [I, I]
c[L] = mod(I, 7)/7 + mod(I, 3)/3
end
``````
1 Like

Do you really need CartesianIndices? A simple solution without them:

``````using StructArrays

xyc = map(Iterators.product(1:nx, 1:ny)) do (i, j)
x, y = b * [i, j]
c = mod(i,7)/7+mod(j,3)/3
(; x, y, c)
end |> StructArray

# access x, y, c arrays as xyc.x and so on
``````
2 Likes

Without any additional packages one could also write this problem as a comprehension:

``````xyc = vec([[b*[i,j]..., mod(i,7)/7+mod(j,3)/3] for i in 0:nx-1, j in 0:ny-1])
x, y, c = [getindex.(xyc, i) for i in 1:3]
``````

It should be possible to write this even simpler.

OP’s nested loops could also be written using the simplified syntax:

``````for i in 0:nx-1, j in 0:ny-1
..
end
``````
1 Like

I learned a lot looking at your solution. I haven’t used Iterators or StructArrays before so this really helpful in expanding my Julia repertoire. I also like that you didn’t need to pre-allocate the arrays. Thanks for the suggestions.

This answered my question directly. But your later suggestion, and @aplavin’s, are even better suggestions (I think). I like that neither one needs preallocated arrays.