Ruby学習 「プロを目指す人のためのRuby入門」 5章

はじめに

プロを目指す人のためのRuby入門Rubyを学習しています。
大事そうな部分や理解が難しかった部分、忘れそうなことについて学習メモを書きます。
今回は第5章「ハッシュやシンボルを理解する」について書いていきます。

記事中のプログラムはirbで動作を確認しました。

ハッシュ

  • ハッシュとはキーと値の組み合わせたデータのこと
{'japan' => 'yen', 'us' => 'dollar'}
=> {"japan"=>"yen", "us"=>"dollar"}
  • 多言語では連想配列やディクショナリと呼ばれる
  • キーが重複した場合、最後の値が有効になる
  • ハッシュ[存在しないキー] = 値 で新しい要素を追加
  • ハッシュ[存在するキー] = 値 で値を更新
  • ハッシュ[キー] で値を取得
  • eachメソッドでハッシュのキーと値の組み合わせを順に取り出すことができる
  • eachメソッドではキーと値は格納した順に取り出される
  • eachメソッドではブロック引数を1つにするとキーと値が配列で格納される
  • eachメソッドではブロック引数を2つにするとキーと値がそれぞれ格納される
  • ==でハッシュ同士を比較するとすべてのキーと値が同じであればtrueが返る
  • sizeメソッドでハッシュの要素数を取得できる
  • deleteメソッドを使うと指定したキーの要素を削除できる
  • deleteメソッドの戻り値は指定したキーがあれば指定した要素の値、なければnil

シンボル

  • シンボルは文字列に似ているが中身は整数でありイミュータブルなオブジェクトである
  • 同じシンボルであればまったく同じオブジェクトなので、メモリ効率が良い
  • シンボルは名前を識別できるようにしたいが、文字列でなくてもいい場合に使う
  • 代表的な利用例はハッシュのキーで、文字列より高速に値を取り出すことができる
  • オブジェクトが持っているメソッド名はシンボルで管理されている

続・ハッシュについて

  • ハッシュのキーにシンボルを使う場合は下記のようにする
currencies = { :japan => 'yen', :us => 'dollar' }
=> {:japan=>"yen", :us=>"dollar"}

currencies[:us]
=> "dollar"
  • シンボルがキーになる場合は=>を省略して、下記のようにも書ける
currencies = { japan: 'yen', us: 'dollar' }
=> {:japan=>"yen", :us=>"dollar"}
  • キー値もシンボルの場合は下記のようになる
{ japan: :yen, us: :dollar }
=> {:japan=>:yen, :us=>:dollar}
  • ハッシュのキーは異なるデータ型を混在させることもできるが分かりづらいのでしない
  • ハッシュの値に異なるデータ型が混在するケースはよくある
  • メソッドのキーワード引数にはシンボルを使う
def  buy_burger(menu, drink: true, potato: true)
  # 省略
end

buy_burger('cheese', drink: true, potato: true)
  • メソッドの引数にデフォルト値が設定されている場合はその引数を省略できる
  • メソッドのキーワード引数は順番を入れ替えられる
  • キーワード引数のデフォルト値は省略できる
  • キーワード引数を使う場合、キーワード引数に一致するハッシュを引数として渡せる
def  buy_burger(menu, drink: true, potato: true)
  # 省略
end
params = { drink: true, potato: false }
buy_burger('fish', params)

ハッシュについてもっと詳しく

  • keysメソッドを使うとハッシュのキーを配列として返す
  • valuesメソッドはハッシュの値を配列として返す
  • has_key?メソッドはハッシュに指定したキーが存在するかどうかチェックする
currencies = {japan: 'yen', us: 'dollars' }
=> {:japan=>"yen", :us=>"dollars"}
currencies.keys
=> [:japan, :us]
currencies.values
=> ["yen", "dollars"]
currencies.has_key?(:us)
=> true
currencies.has_key?(:italy)
=> false
  • **をハッシュの前につけるとハッシュリテラル内でハッシュのキーと値を展開できる
h = { us: 'dollar', india: 'rupee' }
=> {:us=>"dollar", :india=>"rupee"}
{ japan: 'yen', **h }
=> {:japan=>"yen", :us=>"dollar", :india=>"rupee"}
  • ハッシュリテラル.merge(ハッシュ)でも同様の結果になる
  • キーワード引数導入以前はハッシュを引数にして擬似キーワード引数としていた
  • メソッドの引数に**をつけると任意のキーワードをハッシュとして受けとることができる
  • 最後の引数がハッシュであればハッシュリテラルの{}を省略可能
  • 第1引数がハッシュの場合は引数を()でくくらないとエラーになる({}をブロックだと認識されるため)
  • ハッシュはto_aメソッドで配列に変換できる
currencies = {japan: 'yen', us: 'dollar'}
=> {:japan=>"yen", :us=>"dollar"}
currencies.to_a
=> [[:japan, "yen"], [:us, "dollar"]]
  • 配列はto_hメソッドでハッシュに変換できる
array = [[:japan, 'yen'], [:us, 'dollar']]
=> [[:japan, "yen"], [:us, "dollar"]]
array.to_h
=> {:japan=>"yen", :us=>"dollar"}
  • ハッシュに存在しないキーを指定したときはnilが返る
  • ハッシュに存在しないキーを指定したときの戻り値を設定する場合はブロックを使う
hash = Hash.new{ 'none' }
=> {}
hash[:dog]
=> "none"
  • Hash.newにブロックを与えると、ブロック引数にハッシュ自身と見つからなかったキーが渡される
  • Hash.newのブロック引数を使うとハッシュにキーと初期値を設定することができる
hash = Hash.new { |hash, key| hash[key] = 'default' }
=> {}
hash
=> {}
hash[:dog]
=> "default"

シンボルについてもっと詳しく

  • 識別子が数字で始まったりハイフンやスペースが含まれたりするとエラーとなる
  • 上記の場合でもシングルクォートで囲むと使用できる
  • シングルクォートではなくダブルクォートを使うと、式展開を使うことができる
  • ハッシュ作成時に「文字列: 値」の形式で書いた場合も「:文字列」と同様に見なされ、キーがシンボルになる
  • シンボルは%記法を使って作成することができる
  • 文字列とシンボルは別物であり互換性はない
  • to_symメソッドを使うと文字列をシンボルに変換することができる
  • to_sメソッドを使うとシンボルを文字列に変換することができる
  • メソッドによっては文字列とシンボルを同等に扱う(ただし同等に扱わないほうが多い)

感想

シンボルの存在は知っていたが、何に使うものかわからなかったがイミュータブルなので
値が更新されることがなく、ハッシュのキーに設定するとアクセスが高速になるという
メリットがあることが分かった。

参考文献

この記事は以下の情報を参考にして執筆しました。