Julia入門 辞書(ハッシュテーブル)、Set型について
Juliaの配列以外の、データ構造について。
Dict (辞書/ハッシュテーブル)
JuliaだとAssociative Collectionというらしい。
現在Stableのver.0.3と、ver0.4でリテラルでの宣言の仕方が変わるので注意したい。
明示的に型を指定しない方法
まず0.3では以下の通り。
julia> versioninfo() Julia Version 0.3.8 Commit 79599ad (2015-04-30 23:40 UTC) (略) julia> anydict = {"a" => 123, "b" => 456} Dict{Any,Any} with 2 entries: "b" => 456 "a" => 123 julia> normaldict = ["a" => 123, "b" => 456] Dict{ASCIIString,Int64} with 2 entries: "b" => 456 "a" => 123
{} (中カッコ)で宣言すると、{Any, Any}型の辞書が作られる。
[] (各カッコ)で宣言すると、内容から自動で型を推定してくれる。上の例では、おなじ中身でも後者はDict{ASCIIString,Int64}の型になっていることに注意されたし。
これが、ver.0.4だと
julia> versioninfo() (略) julia> anydict = {"a" => 123, "b" => 456} WARNING: deprecated syntax "{a=>b, ...}". Use "Dict{Any,Any}(a=>b, ...)" instead. Dict{Any,Any} with 2 entries: "b" => 456 "a" => 123 julia> normaldict = ["a" => 123, "b" => 456] WARNING: deprecated syntax "[a=>b, ...]". Use "Dict(a=>b, ...)" instead. Dict{ASCIIString,Int64} with 2 entries: "b" => 456 "a" => 123 julia> Dict("a" => 123, "b" => 456) Dict{ASCIIString,Int64} with 2 entries: "b" => 456 "a" => 123
ver.0.3の書き方は両方depricated警告が出る。
後者の型を自動で推理してくれる宣言の仕方は、Dict(key => value, ...) になり、前者の{Any, Any}型でのリテラルの宣言は、方法自体が廃止になった。
型を指定して宣言する方法
これも、ver0.3 / 0.4で異なる。ver.0.3では以下の通り。
julia> versioninfo() Julia Version 0.3.8 Commit 79599ad (2015-04-30 23:40 UTC) (略) julia> (ASCIIString=>Int64)["abc" => 123, "def" => 456] Dict{ASCIIString,Int64} with 2 entries: "abc" => 123 "def" => 456
ver.0.4では以下のとおり。
julia> versioninfo() Julia Version 0.4.0-dev+5114 Commit 894a31e* (2015-05-30 03:57 UTC) (略) julia> Dict{ASCIIString, Int64}("abc" => 123, "def" => 456) Dict{ASCIIString,Int64} with 2 entries: "abc" => 123 "def" => 456
というわけで、中身を指定しながら宣言したい場合に、現在ver.0.3 / 0.4で統一して使用できる記法がないのでした。
どうしても統一したい場合には、以下のように先に空のDictをDict{K, V}()というかたちで宣言して、そこに値を追加する方法が良いと思う。
julia> my_dict = Dict{UTF8String, Int64}() Dict{UTF8String,Int64} with 0 entries julia> my_dict["キー"] = 123 123 julia> my_dict["別のキー"] = 456 456 julia> my_dict Dict{UTF8String,Int64} with 2 entries: "別の… => 456 "キー" => 123 julia> my_dict["キー"] 123
この方法は、ver.0.3 / ver.0.4共通で利用できる。
Dict関連の関数
ざっくりいって、pythonのdict関係と似た関数が用意されている。
Juliaはクラスの概念がないので、第一引数にDictを指定する。
詳しくはver.0.3のドキュメントおよび ver0.4のドキュメントを参照のこと。
よく使いそうな関数の例を以下にあげておく。
julia> get(dict, "unknown", "key not found") # 見つからなかった時のデフォルト値が指定できる "key not found" julia> # キーが見つからなかった時の挙動は、関数でも指定できる(do構文) get(dict, "unknown") do println("key not found!") end key not found! julia> haskey(dict, "foo") # キーがあるかどうかチェック true julia> delete!(dict, "foo") # 指定したキーの項目を削除 Dict{ASCIIString,ASCIIString} with 2 entries: "bar" => "456" "baz" => "789" julia> keys(dict) # キーのイテレータを取得 KeyIterator for a Dict{ASCIIString,ASCIIString} with 2 entries. Keys: "bar" "baz" julia> values(dict) # 値のイテレータを取得 ValueIterator for a Dict{ASCIIString,ASCIIString} with 2 entries. Values: "456" "789"
get関数は、キーがみつからなかった時にdefault値を返すだけだけど、get!関数はみつからなかった場合は指定したキーdefault値またはdefault関数の実行結果を設定する。
julia> dict Dict{ASCIIString,ASCIIString} with 3 entries: "bar" => "456" "baz" => "789" "foo" => "123" julia> get!(dict, "NEW_KEY", "NEW_VALUE") "NEW_VALUE" julia> dict Dict{ASCIIString,ASCIIString} with 4 entries: "bar" => "456" "NEW_KEY" => "NEW_VALUE" "baz" => "789" "foo" => "123" julia> get!(dict, "ANOTHER_KEY") do return "ANOTHER_VALUE" end "ANOTHER_VALUE" julia> dict Dict{ASCIIString,ASCIIString} with 5 entries: "bar" => "456" "NEW_KEY" => "NEW_VALUE" "baz" => "789" "ANOTHER_KEY" => "ANOTHER_VALUE" "foo" => "123"
Set型
pythonのsetと同様、重複がないコレクション型がSet。
Arrayの重複削除くらいしか使わないかな、普段は。
julia> anyset = Set() # 型を指定しないとAny型のSetになる Set{Any}({}) julia> floatset = Set{Float64}() # 型を指定する方法 Set{Float64}({}) julia> strset = Set(["foo", "bar", "baz"]) # 型を自動設定する方法 Set{ASCIIString}({"bar","baz","foo"}) julia> push!(strset, "NEW_VALUE") # 新しい値の追加 Set{ASCIIString}({"NEW_VALUE","bar","baz","foo"}) julia> push!(strset, "foo") # 同じ値は追加しても重複しない Set{ASCIIString}({"NEW_VALUE","bar","baz","foo"}) julia> [v for v in strset] # 配列への変換 4-element Array{Any,1}: "NEW_VALUE" "bar" "baz" "foo"
以上です。