ジュリアで配列の配列を連結するトリック
概要
ジュリアでは、append!
のような関数を通して配列の配列を連結することができるが、バングコンベンション !
が付いているだけに、元の配列を変形させる副作用がある。これを回避するために、スプラットオペレーター ...
を使用するトリックを紹介する。
コード
長さが異なる配列の配列結合
julia> y = [[3, 1, 4], [1, 5], [9, 2]]
3-element Vector{Vector{Int64}}:
[3, 1, 4]
[1, 5]
[9, 2]
julia> [y...;]
7-element Vector{Int64}:
3
1
4
1
5
9
2
セミコロン ;
は配列 y
の列挙 y...
の末尾にくる場合、それ自体で配列の結合になる。これは [y[1]; y[2]; y[3]]
、またはより洗練された形では vcat(x...)
と同じ結果を返す。
縦結合 [x...;]
行列の次元別に一致するならば、行列もまた配列の性質を持つので結合しない理由がない。多次元結合の場合、x...
の後に続くセミコロンの数 n
に対して cat(x..., dims=n)
と同じ結果を返す。このように言葉だけで説明すると理解しにくいので、具体的な例を使って確認してみよう。
julia> x = [reshape(1:4, 2, 2), reshape(5:8, 2, 2), reshape(9:12, 2, 2)];
julia> x[1]
2×2 reshape(::UnitRange{Int64}, 2, 2) with eltype Int64:
1 3
2 4
julia> x[2]
2×2 reshape(::UnitRange{Int64}, 2, 2) with eltype Int64:
5 7
6 8
julia> x[3]
2×2 reshape(::UnitRange{Int64}, 2, 2) with eltype Int64:
9 11
10 12
上記のように二次元配列の配列が与えられているとしよう。
julia> [x...;]
6×2 Matrix{Int64}:
1 3
2 4
5 7
6 8
9 11
10 12
julia> [x...;] == cat(x..., dims = 1)
true
[x...;]
は cat(x..., dims = 1)
と同じ結果として、行列を縦に結合した行列を返す。
横結合 [x...;;]
julia> [x...;;]
2×6 Matrix{Int64}:
1 3 5 7 9 11
2 4 6 8 10 12
julia> [x...;;] == cat(x..., dims = 2)
true
[x...;;]
は ;
が二つあるので cat(x..., dims = 2)
と同じ結果として、行列を横に結合した行列を返す。
高さ結合 [x...;;;]
julia> [x...;;;]
2×2×3 Array{Int64, 3}:
[:, :, 1] =
1 3
2 4
[:, :, 2] =
5 7
6 8
[:, :, 3] =
9 11
10 12
julia> [x...;;;] == cat(x..., dims = 3)
true
テンソルだってできない理由がない。[x...;;;]
は ;
が三つあるので cat(x..., dims = 3)
と同じ結果として、行列を高く積み重ねたテンソルを返す。
全体のコード
y = [[3, 1, 4], [1, 5], [9, 2]]
[y...;]
x = [reshape(1:4, 2, 2), reshape(5:8, 2, 2), reshape(9:12, 2, 2)];
x[1]
x[2]
x[3]
[x...;]
[x...;] == cat(x..., dims = 1)
[x...;;]
[x...;;] == cat(x..., dims = 2)
[x...;;;]
[x...;;;] == cat(x..., dims = 3)
環境
- OS: Windows
- Julia: v1.11.1