Swap cols/rows of a matrix

There is also Base.swapcols!, but again this is an internal function that may disappear in the future. But since it is only a 10-line function that doesn’t depend on any other Base internals it is perfectly reasonable to copy-and-paste it into your code as needed:

# swap columns i and j of a, in-place
function swapcols!(a::AbstractMatrix, i, j)
    i == j && return
    cols = axes(a,2)
    @boundscheck i in cols || throw(BoundsError(a, (:,i)))
    @boundscheck j in cols || throw(BoundsError(a, (:,j)))
    for k in axes(a,1)
        @inbounds a[k,i],a[k,j] = a[k,j],a[k,i]
    end
end

It’s very similar to the suggestions above, except it adds an @inbounds annotation and consequently requires bounds checks before the loop. You could also do e.g.

if isdefined(Base, :swapcols!)
    using Base: swapcols! # assumes the API hasn't changed
else
    function swapcols!(...)
        ...
    end
end

Inspecting Base code can be a useful exercise, even if you end up copy-pasting it for safety, since it usually has been reviewed by multiple people and tries extra hard to be robust and reasonably efficient.

6 Likes