logo

ジュリアで配列の配列を連結するトリック 📂ジュリア

ジュリアで配列の配列を連結するトリック

概要

ジュリアでは、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