Hashのデフォルト値を調べ、自分のまとめ用で作ってみました。
せっかくなのでHashについても簡単にまとめながら記事を書きます。
Hashとは
連想配列とも呼ばれ、配列でありながら、任意のオブジェクト(キー)から任意のオブジェクト(値)を関連づけて配列を生成することができます。
hashの使い方
生成の基本は 変数名 = { "キー" => "値"}
として生成します。
{}
でhashを生成するのを覚えておきます。
p user = { "name" => "Jone", "sex" =>"men", "age" => 23 }
# => {"name"=>"Jone", "sex"=>"men", "age"=>23}
取り出しや変更も可能です。
変数名に対して[]
をつけて、その中に定義してあるkey
を書くだけです。
valueを変更したければ、変数名[key]
に=
で代入の形をとります。
p user["name"] #=> "Jon"
user["age"] = 34
p user["age"] #=> 34
hashをシンボルで使う
hashのkeyは:
シンボルでも定義できます。シンボルを使うことで速度の点で有利になります。
左側につけているシンボルを右側につけることで=>
が省略できます。
p user = { :name => "Jone", :sex =>"men", :age => 23 }
# => {:name=>"Jone", :sex=>"men", :age=>23}
p user = { name: "Jone", sex: "men", age: 23 }
# => {:name=>"Jone", :sex=>"men", :age=>23}
hashのデフォルト値の設定
hashのkeyの値に何もない場合を指定した場合はどうなるでしょうか。
user = { name: "Jone", sex: "men", age: 23 }
p user[:name] # => "Jone"
p user[:height] # => nil
keyに定義していないheight
を指定したところ、nilが出力されました。
nilが出力されるようにしても良い場合もありますが、多くの場合はnilガードを設定して、他の値が出るように設定する必要があります。
これを回避する方法として、keyの値にデフォルト値を設定することができます。
Hash.new
の引数にデフォルト値を設定することができます。
ここからは注意点を踏まえながらやり方を整理します。
デフォルト値を設定する時のHash.newの引数の渡し方
Hash.new([])
で引数を渡した場合、デフォルト値を設定できるものの、すべてのkeyで同じデフォルト値が共有されるように定義されてしまいます。
hash = Hash.new([])
p hash[:a] << "Jone" # => ["Jone"]
p hash[:b] << "Anne" # => ["Jone", "Anne"]
p hash[:a] # => ["Jone", "Anne"]
# hash[:a]のデフォルトで設定した"Jone"が変更されてしまっている
p hash[:a].object_id # => 47010354852980
p hash[:b].object_id # => 47010354852980
# object_idも同じ
では、Hash.new{[]}
にてブロックで渡して、設定してみます。
この場合は、別のデフォルト値を設定できるが、設定した値が消えてしまう。
hash = Hash.new{[]}
p hash[:a] << "Jone" # => ["Jone"]
p hash[:b] << "Anne" # => ["Anne"]
p hash[:a] # => []
# hash[:a]のデフォルトで設定した"Jone"が消えてしまっている
p hash[:a].object_id # => 47099427138120
p hash[:b].object_id # => 47099427137880
# object_idは別のものであるため、別のオブジェクトが生成されているのは確認できる。
これらを解決する方法としてHash.new {|hash, key| hash[key] = [] }
の形で書く方法がある。
ブロックを与えると、対応する値がまだないkeyが呼び出される度に、ブロックを評価するのですべて別のオブジェクトが出力されます。
hash = Hash.new { |hash, key| hash[key] = [] }
p hash[:a] << "Jone" # => ["Jone"]
p hash[:b] << "Anne" # => ["Anne"]
p hash[:a] # => ["Jone"]
# hash[:a]のデフォルトで設定した"Jone"が残ったまま出力されている!
p hash[:c] # => []
# 元のデフォルト[]が出力されている
p hash[:a].object_id # => 47099427138120
p hash[:b].object_id # => 47099427137880
# 別のオブジェクトが生成されている!
p hash # => {:a=>["Jone"], :b=>["Anne"], :c=>[]}
hash[:c]
の動きで、キーに対して何も代入していない場合、デフォルトで設定している[]
が代入されて、出力されているのがわかります。
デフォルト値が破壊されないようにHashのデフォルト値を設定するにはHash.new {|hash, key| hash[key] = [] }
が使えるということを覚えておきたいと思います。
参照
Hash.new { |h, k| h[k] = ... } イディオムの意味
Ruby: Hash.new とデフォルト値