ハッシュとはオブジェクトの集まりのオブジェクトです。配列も同じでしたね。この2つの違いは、配列の要素にはインデックス番号が振られていました。それに対しハッシュは要素にキーというものを設定します。
このキーを指定して値を取り出したり、処理を行ったりします。キーは数値だけではなく、文字列やシンボル、日付なども設定する事が出来ます。
ハッシュオブジェクトの作成方法で最も一般的に使われる2つの方法を紹介していきます。
この方法の書き方は以下のようになります。
{キー => 値, キー => 値}
上記例では2つの要素を記述しています。このようにキーを設定していきます。またキーにシンボルを設定する事も出来ます。その場合は以下のようになります。
{キー: 値, キー: 値}
では実際にハッシュオブジェクトを作成してみましょう。
member = {"name" => "山田", "team" => "A"}
p a["name"]
#=> "山田"
p a["team"]
#=> "A"
member2 = {name: "田中", team: "B"}
p member2[:name]
#=> "田中"
p member2[:team]
#=> "B"
設定したキーを指定し取り出すことも出来ていますね。
この方法で作成するとき引数を指定すればその値は、存在しないキーを指定された際に返す値となります。では例をみてみましょう。
test = Hash.new("そのキーは存在しません")
p test
#=> {}
p test[1]
#=> "そのキーは存在しません"
「1」というキーは存在しないので、引数で指定されているデフォルト値を返しています。では引数を指定しない場合を見てみましょう。
test2 = Hash.new
p test2
#=> {}
p test2[1]
#=> nil
この場合に存在しないキーを指定すると、「nil」が返ります。
この「Hash.new」でのデフォルト値の設定方法はもう1つ存在します。では見てみましょう。
test3 = Hash.new{|h, k| h[k] = k.downcase}
p test3["A"]
#=> "a"
このようにブロックを使ってデフォルト値を設定する事が出来ます。この例の場合は指定された存在しないキーを小文字にしたものをデフォルト値としています。
前セクションでも取り上げていますが、ハッシュ内の要素を取り出したり要素を作成したり、値を変更する方法を紹介していきます。
配列と同様に「[ ]」を使用する方法です。
test = Hash.new
test[1] = "a" #要素を作成
p test
#=> {1=>"a"}
test[1] = "A" #キーを指定し、値を変更
p test
#=> {1=>"A"}
p test[1] #キーを指定し、値を取り出す
#=> "A"
「[ ]」と同じように要素の作成を行う事が出来ます。キーや値は引数で指定します。
test2 = Hash.new
test2.store(1, "a")
p test2
#=> {1=>"a"}
こちらのメソッドはキーを指定し値を取り出すためのメソッドです。
test3 = Hash.new("そのキーは存在しません")
test3[1] = "a"
p test3
#=> {1=>"a"}
p test3.fetch(2)
#KeyError: key not found: 2
p test3.fetch(1, "no key")
#=> "a"
p test3.fetch(2, "no key")
#=> "no key"
「[ ]」を使用した際と異なる点があります。それは、デフォルト値を設定していたとしても存在しないキーを指定した場合はエラーとなる点です。これを回避するには2つ目の引数でキーが存在しない場合に返す値を指定します。そうするとキーが存在すれば値を返し、存在しなければ第2引数で指定した値を返します。
また、この「fetch」メソッドは第2引数にあたる場所でブロックを使用する事が出来ます。第2引数なのでブロックの中の処理の結果がキーが存在しない場合に返す値となります。
test4 = Hash.new
p test4.fetch(0){"no key".upcase}
#=> "NO KEY"
この2つのデフォルト値の設定は「Hash.new」で設定したデフォルト値よりも優先されます。
先ほどご紹介したメソッド等は、値を1つずつ取り出すというものでした。このセクションではキーや値、要素を1つの配列にして取り出すという方法を学んでいきましょう。
ハッシュ内のキーだけをまとめて取り出したいときは、この「keys」というメソッドを使います。ではやってみましょう。
foo = {1 => "a", 2 => "b", 3 => "c"}
p foo.keys
#=> [1, 2, 3]
こちらはハッシュ内の値のみをまとめて取り出します。
p foo.values
#=> ["a", "b", "c"]
こちらのメソッドを使うと、キーと値のペアの配列を作り、このペアの配列を1つにまとめた配列を返します。
p foo.to_a
#=> [[1, "a"], [2, "b"], [3, "c"]]
キーや値をイテレータで1つずつ取り出したり、処理を実行する事が出来ます。キーと値それぞれにその為のメソッドが存在します。
キーを取り出したり処理を実行するためのイテレータです。
foo.each_key do |k|
puts "キー→#{k}"
end
#キー→1
#キー→2
#キー→3
値を取り出したり処理を実行するためのイテレータです。
foo.each_value do |v|
puts "値→#{v}"
end
#値→a
#値→b
#値→c
あるオブジェクトがハッシュ内のキーや値と同じものであるかを調べることが出来るメソッドを紹介していきます。これらのメソッドは同じであれば「true(真)」を返します。
ハッシュ内のキーの中にオブジェクトと同じものがあるかを調べるメソッドは4種類存在します。全て同じ働きをし使用方法も同じです。ですのでプログラムの読みやすさの為に使い分けるという事も出来ますね。使い方については、引数で調べたいオブジェクトを指定しメソッドを呼び出します。
foo = {1 => "a"}
p foo.key?(1)
#=> true
p foo.has_key?(2)
#=> false
p foo.include?(1)
#=> true
p foo.member?(2)
#=> false
こちらも引数でオブジェクトを指定します。この2つは働きも使い方も同じです。
p foo.value?("a")
#=> true
p foo.has_value?("b")
#=> false
ハッシュ内に存在するキーの数を調べるメソッドについて学んでいきましょう。
この2つのメソッドは文字列のレッスンなどでも取り上げましたね。文字列の場合は文字数を調べるという事でしたが、ハッシュの場合はハッシュ内に存在するキーの数を調べるメソッドとなります。この2つのメソッドも同じ働き、同じ使い方をします。
test = {1 => "a", 2 => "b", 3 => "c"}
p test.size
#=> 3
p test.length
#=> 3
キーの数が0、つまりハッシュ内にキーが存在するかどうかを調べるメソッドです。こちらも文字列などの章レッスンでも取り上げましたね。
test = {1 => "a", 2 => "b", 3 => "c"}
if test.empty?
puts "キーがありません"
else
puts "キーが存在します"
end
#キーが存在します
ハッシュ内の要素を指定し削除する事も出来ます。では使い方を見ていきましょう。
削除したい要素の指定は、キーを引数で指定することによって行います。こちらは破壊的メソッドです。
test = {1 => "a", 2 => "b", 3 => "c"}
test.delete(1)
p test
#=> {2=>"b", 3=>"c"}
また第2引数としてブロックを使用すれば「delete」メソッドの引数で指定されたキーが存在しない場合に返す値を設定出来ます。
p test.delete(0){|k| "#{k}というキーは存在しません"}
=> "0というキーは存在しません"
この2つのメソッドは、条件を設定して当てはまれば削除というようにしたい場合に使用します。この2つのメソッドの違いは、条件にあてはまる要素がなかった場合の返り値です。「reject!」は「nil」、「delete_if」は何も変更がされていない配列をそのまま返します。
test2 = {a: 2, b: 3, c: 4}
p test2.reject!{ |k, v| v.odd? }
#=> {:a=>2, :c=>4}
p test2
#=> {:a=>2, :c=>4}
p test2.delete_if{ |k, v| v.odd? }
#=> {:a=>2, :c=>4}
ハッシュの初期化を行う方法は2つあります。「clear」というメソッドを使う方法と「Hash.new」とする方法です。この2つの違いは、例えば「a」というハッシュが存在するとして、「a」を参照する他の変数「b」が存在していた場合に「clear」だと「b」にも初期化が反映され、「Hash.new」だと「a」のみ初期化され「b」の値はそのままという点です。では実際にやってみましょう。
a = {1 => "a", 2 => "b"}
b = a
a.clear
p a
#=> {}
p b
#=> {}
a = {1 => "a", 2 => "b"}
b = a
a = Hash.new
p a
#=> {}
p b
#=> {1=>"a", 2=>"b"}
ハッシュ自体を値としてキーを設定しハッシュの中にハッシュを要素として持つことが出来ます。では例を見てみましょう。
test = {1 => {"a" => "A", "b" => "B"},
2 => {"c" => "C", "d" => "D"}}
p test[2]["d"]
#=> "D"
取り出す際などは、配列と同じように「[ ]」を2つ使い要素を指定します。では2つのハッシュを連結してみましょう。
こちらは非破壊的メソッドです。
a = {1 => "A"}
b = {2 => "B"}
test = a.merge(b)
p test
#=> {1=>"A", 2=>"B"}
p a
#=> {1=>"A"}
p b
#=> {2=>"B"}
こちらは破壊的メソッドになります。以下例で言うとハッシュ「a」の値を連結した結果に書き換えます。
test2 = a.merge!(b)
#=> {1=>"A", 2=>"B"}
p a
#=> {1=>"A", 2=>"B"}
p b
#=> {2=>"B"}
「!」は付いていませんがこちらも破壊的メソッドです。「merge」や「merge!」と使い方は同じで、「merge!」とは働きも同じです。
test3 = a.update(b)
p test3
#=> {1=>"A", 2=>"B"}
p a
#=> {1=>"A", 2=>"B"}
p b
#=> {2=>"B"}
ハッシュとはオブジェクトの集まりです。キーと値のセットが1つの要素となります。
値を取り出したり処理を行いたい場合は、キーで指定をしましょう。
無料ビデオ講座のお知らせ
Skillhub [スキルハブ]では無料の動画講座を多数公開しています。他校だと数万円するような講座が無料で受講できます。