How to concatenate vectors to be a matrix, not a vector

Hi, I tried a few solutions(vcat, hcat, [;], [,], etc), but haven’t got what I want.

julia> function minesweeper(input)
           allarr = []
           for line in input
               arr = split(line, "")
               allarr = [allarr; arr]
           end
           println(allarr)
       end
minesweeper (generic function with 1 method)

julia> minefield = ["123",
                    "456",
                    "789"]
3-element Vector{String}:
 "123"
 "456"
 "789"

julia> minesweeper(minefield)
Any["1", "2", "3", "4", "5", "6", "7", "8", "9"]

What I’d like to have is:
[[“1”, “2”, “3”],
[“4”, “5”, “6”],
[“7”, “8”, “9”]]

Thank you!

push!(allarr,arr)

ps: use allarr = Vector{String}[] so you don’t get a container of type Any.

1 Like

this is not a matrix, this is a vector of vector

4 Likes

You can do a comprehension and it will infer the type correctly.

julia> [split(line, "") for line in minefield]
3-element Vector{Vector{SubString{String}}}:
 ["1", "2", "3"]
 ["4", "5", "6"]
 ["7", "8", "9"]
1 Like

Or simply,

julia> split.(minefield, "")
3-element Vector{Vector{SubString{String}}}:
 ["1", "2", "3"]
 ["4", "5", "6"]
 ["7", "8", "9"]

But if lines are gauranteed to have the same length, this will be much faster:

julia> [[string(minefield[i][j]) for i=1:3] for j=1:3]
3-element Vector{Vector{String}}:
 ["1", "4", "7"]
 ["2", "5", "8"]
 ["3", "6", "9"]
2 Likes

It’s there a reason you’re using a Vector{Vector{String}} (or technically Vector{Vector{Any}})? This seems like a good use case for a Matrix{Int} from the example.

Or as only chars are being considered here, one could simply do:

collect.(minefield)

3-element Vector{Vector{Char}}:
 ['1', '2', '3']
 ['4', '5', '6']
 ['7', '8', '9']
1 Like

Answering your actual question, to concatenate vectors into a matrix, you can use matrix literals:

julia> u = [1, 2, 3]; v = collect("abc");

julia> [u v]
3×2 Array{Any,2}:
 1  'a'
 2  'b'
 3  'c'

This works because matrix literals have spaces to separate elements horizontally, and semicolons to separate rows:

julia> [1 2; 3 4]
2×2 Array{Int64,2}:
 1  2
 3  4

If you want your code to use this, you’ll notice that, since allarr = [] has zero columns, the first iteration runs into a dimension-mismatch problem.
You can solve this by initially making allarr an empty 3×0 matrix (yes, that’s different to []!) like so: fill('A', 3, 0) or Matrix{Char}(undef, 3, 0).

function minesweeper(input)
    allarr = Matrix{Char}(undef, 3, 0)  # initialise 3×0 matrix of `Char`s with arbitrary `undef`ed entries
    for line in input
        arr = collect(line)
        allarr = [allarr arr]
    end
    permutedims(allarr)
end

Notice I used collect(line) instead of split(line, "") to give a Vector{Char} and transposed the final matrix with permutedims to match the input.

This produces a proper Matrix (aka 2-dimensional Array), and not a vector of vectors.