I often need to loop through the upper/lower triangular section of a matrix and usually end up doing something like:
A = reshape(1:25,5,5)
for j in axes(A,2)
for i in axes(A,1)
if i>j
@show A[i,j]
end
end
end
This is fine but can lead to code with way too many indents. You could get rid of the if statement, but its still very clunky and takes a second to figure out whats going on:
for j in axes(A,2)
for i in j+1:size(A,1)
@show A[i,j]
end
end
I came up with simpler solution and wanted to share it. Basically Iterators does all the heavy lifting.
It’s pretty versatile like you could change the comparison to include the diagonal and there’s no fussing around with adding one to indices. You could probably even get it to work with CartesianIndices if you wanted. Feel free to suggest improvements
Oh I don’t think I would have ever thought of making a generator of maps, interesting. I guess you could skip right to the generator as well:
lowTriIter3(A::AbstractMatrix) =
((i,j) for j in axes(A,2) for i in j+1:size(A,1))
I do like that these methods skip over the additional iterations but I do wish they avoided the i+1:size(A,1) bit. Also I made my version more complicated than it need to be. I think I was worried about axes(A) having more than two iterators, but it won’t because A is already a matrix:
I did, but that’s a fair point! It’s wild how many ways you can accomplish the same task.
I think I liked my version because it abstracted away the need to think about indices. Like if I wanted to change this nested loop to iterate over the upper triangle it would take me a minute to figure out versus just flipping a less-than sign. I get that’s just a preference though