Search code examples
arraysmatrixjuliacatternary

repeat vectors vertically in an Array / Matrix, n times cat


I have

x = collect(1:9)
y = repeat([1],9)

producing

9-element Vector{Int64}:
 1
 2
 3
 4
 5
 6
 7
 8
 9

9-element Vector{Int64}:
 1
 1
 1
 1
 1
 1
 1
 1
 1

And want to glue the two vectors together vertically, whereas some of the matrix columns are x, others y. I found that I can do that equivalently by running either one of those commands:

c0 = [x y x x x]
c1 = cat(x,y,x,x,x,dims=2)

producing

9×5 Matrix{Int64}:
 1  1  1  1  1
 2  1  2  2  2
 3  1  3  3  3
 4  1  4  4  4
 5  1  5  5  5
 6  1  6  6  6
 7  1  7  7  7
 8  1  8  8  8
 9  1  9  9  9

Now, I would like to dynamically put together a matrix with x and y columns based on a control vector, V, that can differ in length. I tried to do it in the following way, however, I will get a different data structure:

V = [false true false false false]
[v ? x : y for v in V]

producing:

1×5 Matrix{Vector{Int64}}:
 [1, 1, 1, 1, 1, 1, 1, 1, 1]  [1, 2, 3, 4, 5, 6, 7, 8, 9]  [1, 1, 1, 1, 1, 1, 1, 1, 1]  [1, 1, 1, 1, 1, 1, 1, 1, 1]  [1, 1, 1, 1, 1, 1, 1, 1, 1]

How can I solve this? I strictly need this structure, and I have a strong interest/preference in using the beautiful Julia fast vector/array code style, avoiding any multi-line for loops.


Solution

  • You should be able to use

    V = [true, false, true, true, true]
    reduce(hcat, [v ? x : y for v in V])
    

    This will first create the vector as you show and then stack the vector together horizontally.

    An alternative is first create a matrix of the right size using for example

    M = zeros(Int64, length(x), length(V))

    and then fill it with the vectors you need

    for (idx, i) in enumerate(V)
        M[:, idx] = i ? x : v
    end
    

    EDIT:

    Adding this terse version proposed by @DonaldSeinen

    y .* .!V + x .* V