Appending to an array along dimension n

I am trying to write a function that fills rows along the ith dimension n many times. Let’s call this function fill_n_times. If the function takes parameters

fill_n_times(M, n, fill_elem; dim = 1)

Then my expected output is

julia> rand(Int8, 2, 2)
2×2 Array{Int8,2}:
  28  23
 -47  54

julia> fill_n_times(A, 2, 3, dim = 1) # repeat the value 3 twice along the first dimension
4×2 Array{Int64,2}:
  28  23
 -47  54
   3   3
   3   3

The closest I have to a function like this is as follows, but it doesn’t quite do what I want (I keep getting a dimension mismatch):

function fill_n_times(M, n, fill_elem; dim = 1)
    return cat(M, collect(Iterators.repeated(fill(fill_elem, size(M, dim)), n))..., dims = dim)
end

# OR

function fill_n_times(M, n, fill_elem; dim = 1)
    return cat(M, fill(fill_elem, (n, size(M, dim))), dims = dim)
end

Regarding the latter function, I have to change (n, size(M, dim)) to (size(M, dim), n) for dim = 2 (and that’s only for two-dimensional arrays!).

How can I generalise this? I have not very much experience working with higher dimensions.

I think you should work out the size of the new block first – it’s the same as that of A, except along the indicated dimension, where it has size n.

julia> function fill_n_times(A::AbstractArray{<:Any,N}, n::Integer, el; dims::Integer=1) where {N}
        sz = ntuple(d -> d==dims ? n : size(A,d), max(N,dims))
        cat(A, fill(el, sz); dims=dims)
       end;

julia> A = rand(Int8, 2, 2);

julia> fill_n_times(A, 2, 101; dims = 1)
4×2 Matrix{Int64}:
  61   -7
 -31  -36
 101  101
 101  101

julia> fill_n_times(A, 2, 44; dims = 4)
2×2×1×3 Array{Int64, 4}:
[:, :, 1, 1] =
  61   -7
 -31  -36

[:, :, 1, 2] =
 44  44
 44  44

[:, :, 1, 3] =
 44  44
 44  44
1 Like

@mcabbott ahh, thanks so much. That is a clever solution I probably wouldn’t have thought of…