Julia入門 配列
引き続き、Julia入門。
本日は配列について。型の話が避けられなかったので、ちょっとだけその話もする。
配列の宣言
julia> a = [1, 2, 3] 3-element Array{Int64,1}: 1 2 3 julia> arr = ["this", "is", "an", "array"] 4-element Array{ASCIIString,1}: "this" "is" "an" "array" julia> arr[4] "array" julia> arr[1] "this"
上記のように、[ ] で作る。
非常に重要なポイントとして、配列の最初のインデックスは0ではなくて1。
REPLからの出力に出ているが、、初期化の際の内容によって、何の配列なのかが決まる。
1番目の例では整数であるInt64、2番目の例では文字列のASCIIString型になっている。
Juliaでの文字列はASCII文字列のASCIIStringと他バイト文字のUTF8Stringで型が異なるため、上記のarrに日本語を追加するとエラーになる。
julia> push!(arr, "ゆにこーど") ERROR: invalid ASCII sequence in convert at /opt/homebrew-cask/Caskroom/julia/0.3.8/Julia-0.3.8.app/Contents/Resources/julia/lib/julia/sys.dylib in push! at array.jl:460
日本語を追加する予定があるのであれば、宣言のときにUTF8String[]という形式で、型を指定してあげればよい。
julia> utf8_array = UTF8String["new", "utf8string", "array"] 3-element Array{UTF8String,1}: "new" "utf8string" "array" julia> push!(utf8_array, "日本語でおk") 4-element Array{UTF8String,1}: "new" "utf8string" "array" "日本語でおk"
どんな型でも入る配列が希望であれば、Any型というものがある。
julia> any_array = Any[123, "数字", 1.54] 3-element Array{Any,1}: 123 "数字" 1.54 julia> typeof(any_array) Array{Any,1} julia> for val = any_array println(val, " ----> ", typeof(val)) end 123 ----> Int64 数字 ----> UTF8String 1.54 ----> Float64
上記のようにtypeof関数を使えば、対象の変数の型を調べることができる。
基本的なメソッド
julia> arr = UTF8String["a", "b", "c"] 3-element Array{UTF8String,1}: "a" "b" "c" julia> length(arr) # 長さ 3 julia> push!(arr, "d") # エレメントの追加 4-element Array{UTF8String,1}: "a" "b" "c" "d" julia> push!(arr, "e", "f") # 複数のエレメント追加 6-element Array{UTF8String,1}: "a" "b" "c" "d" "e" "f" julia> new_arr = ["x", "y", "z"] 3-element Array{ASCIIString,1}: "x" "y" "z" julia> append!(arr, new_arr) # 配列の結合 9-element Array{UTF8String,1}: "a" "b" "c" "d" "e" "f" "x" "y" "z" julia> insert!(arr, 7, "G") # 指定したインデックスにエレメントを追加 10-element Array{ASCIIString,1}: "a" "b" "c" "d" "e" "f" "G" "x" "y" "z"
そのほかのメソッドはこちらを参照のこと。
なお、上記のpop!, insert!, append! など、ビックリマークがついているとおりどれも破壊的な関数で、指定した配列自体が変更される。
ちょっと関数型っぽくないが、Julia全体として、あまりイミュータビリティにはこだわりがないというか。
上記の関数に非破壊的なバージョンもないし。なんとなくそういうポリシーだと思っておくと良いと思う。
2次元配列
これまたちょっとトリッキーなところです。
julia> array = [[1, 2], [3, 4], [5, 6]] 6-element Array{Int64,1}: 1 2 3 4 5 6
直感的に上記のようにかくと、すべて連結されてただの1次元の配列になる。
シンプルな2次元配列の宣言と初期化は以下の通り。
julia> array = [1 2; 3 4; 5 6] 3x2 Array{Int64,2}: 1 2 3 4 5 6 julia> array[2,2] 4
Juliaでは、「2次元配列」と「配列の配列」は全く異なるものであることを覚えておこう。
配列の配列を宣言したければ、以下の通り。
julia> array_of_array = Array{Int64}[[1, 2, 3], [4, 5, 6], [7, 8, 9]] 3-element Array{Array{Int64,N},1}: [1,2,3] [4,5,6] [7,8,9] julia> array_of_array[3][2] 8
3次元以上の配列
3次元以上の配列はリテラルでは宣言と同時に初期化はできない。
Array(T, d1, d2, d3) という形式で宣言し、部分ごとに割り当てる。
julia> three_d = Array(UTF8String, 2, 2, 3) 2x2x3 Array{UTF8String,3}: [:, :, 1] = #undef #undef #undef #undef [:, :, 2] = #undef #undef #undef #undef [:, :, 3] = #undef #undef #undef #undef jjulia> three_d[:, :, 1] = UTF8String["the" "first"; "2x2" "array"] 2x2 Array{UTF8String,2}: "the" "first" "2x2" "array" julia> three_d[:, :, 2] = UTF8String["the" "second"; "2x2" "array"] 2x2 Array{UTF8String,2}: "the" "second" "2x2" "array" julia> three_d[:, :, 3] = UTF8String["the" "third"; "2x2" "array"] 2x2 Array{UTF8String,2}: "the" "third" "2x2" "array" julia> three_d 2x2x3 Array{UTF8String,3}: [:, :, 1] = "the" "first" "2x2" "array" [:, :, 2] = "the" "second" "2x2" "array" [:, :, 3] = "the" "third" "2x2" "array" julia> three_d[1, 2, :] 1x1x3 Array{UTF8String,3}: [:, :, 1] = "first" [:, :, 2] = "second" [:, :, 3] = "third"
上記のように:(コロン)は対象の次元のデータすべて、という意味になる。
数字の場合には、上記の形式で宣言すると初期化されていない状態(変な数字が入る)になってしまうので、zeros関数で宣言するのが良いと思う。
下の例は各次元が2ずつの4次元配列を宣言する例。
num_array = zeros(Float64, 2, 2, 2, 2) 2x2x2x2 Array{Float64,4}: [:, :, 1, 1] = 0.0 0.0 0.0 0.0 [:, :, 2, 1] = 0.0 0.0 0.0 0.0 [:, :, 1, 2] = 0.0 0.0 0.0 0.0 [:, :, 2, 2] = 0.0 0.0 0.0 0.0
例えば640x480xRGBA各8bitの画像データを配列で表現した時に一番上の列を全部255にしたかったら以下のような形。
ちなみにrandでzerosやArrayと同じ形式で、ランダムな数字の入った配列を宣言できる。
2行目のfillで、指定した形を1番目の引数で埋めた配列を作れる。
(pythonで[255] * 16 とやっていたのを、juliaではfill(255, 16) と書く)
julia> vga_rgba_data = rand(UInt8, 640, 480, 4) (略) julia> vga_rgba_data[:, 1, :] = fill(255, 640, 1, 4) 640x1x4 Array{Int64,3}: (略)