LoginSignup
2
0

More than 1 year has passed since last update.

【Ruby】Hashのデフォルト値の設定

Posted at

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 とデフォルト値

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0