Nice way to iterate through a triangular matrix

RobertGregg
Sun, 16 Jul 2023 01:48:01 +0000
General Usage

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.

lowTriIter(ax1, ax2) = Iterators.filter(i -> first(i)>last(i),
                                        Iterators.product(ax1,ax2) )

lowTriIter(A::AbstractMatrix) = lowTriIter(axes(A)...)

Which leads to code that looks like this:

for (i,j) in lowTriIter(A)
    @show A[i,j]
end

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

11 posts - 7 participants