I want to iterate a function whose argument is a vector. The vectors to iterate on are the columns of a matrix. I was “slicing” the matrix into columns following Converting a matrix into an array of arrays and then iterate over the new array whose entries are the vectors I want.
I think it is not optimal and that is my first question: If all I want is to iterate over the columns of a matrix, then shouldn’t I define an iterator (instead of copying the whole matrix)?
So, I came up with the following code which does the trick, but I am not sure whether this is the right way to define such iterator (e.g. are the last two lines strictly necessary? defining the length gives me problems with the length function…)
struct AbstractMatrixColumn
M::AbstractMatrix
end
function Base.iterate(M::AbstractMatrixColumn)
state = 1
return Base.iterate(M,state)
end
function Base.iterate(M::AbstractMatrixColumn, state)
if state > size(M.M,2)
next = nothing
else
next = M.M[:,state], state+1
end
return next
end
Base.length(M::AbstractMatrixColumn) = size(M.M,2)
Base.eltype(M::AbstractMatrixColumn) = typeof(M.M[:,1])
Coming back to Converting a matricx into an array of arrays, now we can use this iterator to collect the columns of a matrix M
with collect(AbstractMatrixColumns(M))
, but it is much slower. Is it supposed to be or it is a problem with my implementation?
function slicematrix_column(M::AbstractMatrix{T}) where T
return [M[:,i] for i in 1:size(M,2)]
end
n = 1000;
N = rand(n,n);
@btime collect(AbstractMatrixColumn($N));
@btime slicematrix_column($N);
> julia
2.083 ms (6945 allocations: 7.87 MiB)
1.329 ms (1003 allocations: 7.76 MiB)