Juliaで2次元配列と行列の間の変換方法
概要
Juliaで2次元配列と行列の間を切り替えるヒントを紹介する1。おそらくJulia 1.7以下の環境では、最もJuliaらしく、シンプルで、速く、美しい方法だろう。
コード
ここで紹介された方法だけではなく、行列と2次元配列の間を行き来する方法は数えきれないほどある。ただコードを書くだけでなく、目標そのものが難しくないから、Julia独特の構文がどのように使用されたのかも考えながら読む方がいい。
行列から2次元配列へ
julia> M = rand(0:9, 3, 10)
3×10 Matrix{Int64}:
 2  4  0  1  8  0  9  2  5  7
 5  2  1  5  4  3  7  2  7  3
 7  8  1  9  0  3  2  4  1  3
上のような行列を2次元配列に変えてみよう。
julia> [eachrow(M)...]
3-element Vector{SubArray{Int64, 1, Matrix{Int64}, Tuple{Int64, Base.Slice{Base.OneTo{Int64}}}, true}}:
 [2, 4, 0, 1, 8, 0, 9, 2, 5, 7]
 [5, 2, 1, 5, 4, 3, 7, 2, 7, 3]
 [7, 8, 1, 9, 0, 3, 2, 4, 1, 3]
julia> [eachcol(M)...]
10-element Vector{SubArray{Int64, 1, Matrix{Int64}, Tuple{Base.Slice{Base.OneTo{Int64}}, Int64}, true}}:
 [2, 5, 7]
 [4, 2, 8]
 [0, 1, 1]
 [1, 5, 9]
 [8, 4, 0]
 [0, 3, 3]
 [9, 7, 2]
 [2, 2, 4]
 [5, 7, 1]
 [7, 3, 3]
eachrow()とeachcol()は行列の行と列を一行ずつ抽出するジェネレータを返す2、そしてスプラットオペレータを通じてこれらを可変配列として扱い3、角括弧[]の中に入れることで、自然に配列になる。
2次元配列から行列へ
julia> A = [rand(0:9,3) for _ in 1:10]
10-element Vector{Vector{Int64}}:
 [5, 4, 9]
 [9, 7, 6]
 [9, 9, 6]
 [5, 9, 0]
 [0, 2, 8]
 [3, 9, 5]
 [1, 6, 0]
 [5, 7, 7]
 [1, 3, 5]
 [5, 4, 1]
上のような2次元配列を行列にしてみよう。
julia> hcat(A...)
3×10 Matrix{Int64}:
 5  9  9  5  0  3  1  5  1  5
 4  7  9  9  2  9  6  7  3  4
 9  6  6  0  8  5  0  7  5  1
julia> hcat(A...)'
10×3 adjoint(::Matrix{Int64}) with eltype Int64:
 5  4  9
 9  7  6
 9  9  6
 5  9  0
 0  2  8
 3  9  5
 1  6  0
 5  7  7
 1  3  5
 5  4  1
julia> vcat(A...)
30-element Vector{Int64}:
 5
 4
 9
 9
 7
 6
 9
 9
 ⋮
 7
 1
 3
 5
 5
 4
 1
配列を統合するhcat()関数を使えばいい。4 基本的にhcat()とvcat()はフォールド関数であり、可変引数関数であるため、2次元配列の要素である1次元配列を直接引数としてスプラットオペレータを通じて渡さなければならない。
全体のコード
# matrix to 2d array
M = rand(0:9, 3, 10)
[eachrow(M)...]
[eachcol(M)...]
# 2d array to matrix
A = [rand(0:9,3) for _ in 1:10]
hcat(A...)
hcat(A...)'
vcat(A...)
環境
- OS: Windows
 - julia: v1.7.0
 
