すでにメンバーの場合は

無料会員登録

GitHubアカウントで登録 Pikawakaが許可なくTwitterやFacebookに投稿することはありません。

登録がまだの方はこちらから

Pikawakaにログイン

GitHubアカウントでログイン Pikawakaが許可なくTwitterやFacebookに投稿することはありません。

Rails

【Rails】 6.Rubyのハッシュを学ぼう

※ カリキュラムでは、Cloud9のエディタやターミナルを利用します。
まだ用意していない方は「AWS Cloud9を準備しよう」を参考に導入してください。

ハッシュのイメージを図で掴もう

まずは「ハッシュとは何か」を図で理解していきましょう。

ハッシュ(Hash)とは

ハッシュとは任意のオブジェクトを使って、複数のデータ(オブジェクト)への参照をまとめて管理できるオブジェクトのことです。

ハッシュと似たような存在として、配列があります。
配列も「複数のデータへの参照をまとめて管理できるオブジェクト」だと学びましたね。

配列の場合は、名札に0からの番号が自動で順番に割り当てられます。

配列オブジェクト

ハッシュの場合は、名札の名前を自由に付けることができます。

以下の図のように、ハッシュは配列と同様に複数の名札が連結して並べられていますが、名札には文字列などの任意のオブジェクトを使って、自由に名前を付けることができます。

ハッシュオブジェクト

上の図では、"name""age"などの文字列を使い、名札に名前を付けています。

文字列や数値など複数の種類のオブジェクトを格納する場合は、「番号で管理する配列」よりも「自由に名前を付けられるハッシュ」の方が管理しやすいです。

ハッシュの管理のしやすさ

ポイント
  1. ハッシュは、複数のオブジェクトへの参照をまとめて管理できる
  2. ハッシュは、複数の名札が連結して自由に名前を付けられるイメージ
  3. 複数の種類のオブジェクトを格納する場合は、ハッシュの方が識別しやすい

ハッシュの要素

ハッシュの中の名札は「要素」と呼ばれます。
Rubyでは、各要素はオブジェクトのことを指し示しています。

ハッシュの要素

要素を特定することで、オブジェクトを参照することができます。要素の特定には、「キー」と呼ばれるものを使います。

ハッシュのキー

要素に割り当てた任意のオブジェクトは「キー」と呼ばれます。
各要素を特定するために「キー」が使われます。

ハッシュのキー

キーを指定することで、キーに対応するオブジェクトを参照することができます。

ぴっかちゃん

配列の場合は「添字」だったけど、ハッシュの場合は「キー」なんだね!

ハッシュは変数に代入できる

ハッシュ自体もオブジェクトなので、変数に代入することができます。

ハッシュを変数に代入すると、以下の図のように1人の男性のデータを管理するハッシュに対してuserと名付けることができます。

ハッシュを変数に代入

変数に代入したオブジェクトは、変数名を指定することで参照することができましたが、ハッシュを代入した場合は、どのように指定すればよいでしょうか。

以下の図のように変数名(user)だけでは、ハッシュ自体を指していることになり、各要素の値を参照することができません。

要素の値を取得できない例

そこで、要素を特定することができる「キー」の登場です。
変数名に加えて「キー」を指定することで、キーに対応するオブジェクトを参照することができます。

キーを使用する

ハッシュのイメージが掴めたところで、次はRubyを使ってハッシュを学ぼう

ぴかわかさん
ポイント
  1. ハッシュは変数に代入することができる
  2. 変数名だけでは、ハッシュ自体を参照することになる
  3. キーに対応するオブジェクトを参照するには、変数名に加えてキーを指定する

ハッシュの生成方法とは

ハッシュの作り方について学んでいきましょう。

ハッシュ

ハッシュの生成方法

ハッシュは、{}で生成することができます。
以下の書き方では、何もデータを持たない空のハッシュが生成されます。

ハッシュの作り方 | 空のハッシュが生成される
1
{}

キーと値の組み合わせを格納するハッシュを生成するには、以下のように記述します。
キーと値は=>を使って対応付けます。

ハッシュの作り方 | キーと値の組み合わせを格納する
1
{ キー =>  }

以下のように,で区切ることで、複数のキーと値の組み合わせが格納できます。

ハッシュの作り方 | 複数のキーと値の組み合わせを格納する
1
{ キー1 => 1, キー2 => 2, キー3 => 3 }

また、以下の赤い箇所のように「半角スペース」を{の後や}の前、=>前後、カンマ(,)の後に入れることで、コードが読みやすくなります。

半角スペースを入れる箇所

さらに改行して記述することもできます。

ハッシュの作り方 | 改行する場合
1
2
3
4
5
{
  キー1 => 1,
  キー2 => 2,
  キー3 => 3
}

それでは、前述の例を使ってハッシュの生成方法を確認してみよう

ぴかわかさん

図とコードでハッシュの生成方法を確認しよう

前述の例で使用した図を使って、ハッシュの生成方法を確認してみましょう。

キーと値の対応付けは、以下のようになります。

キーと値の対応付け

上の図をソースコードにする場合は、以下のようにキーと値を指定します。

複数のキーと値の組み合わせを格納する
1
{ "name" => "田中 太郎", "age" => 18, "gender" => "男" }

改行する場合は、以下のように書きます。

改行する場合
1
2
3
4
5
{
  "name" => "田中 太郎",
  "age" => 18,
  "gender" => "男"
}
ぴっかちゃん

次は実際に手を動かしてハッシュを生成していこう!

ハッシュを生成してみよう

それでは、実際にハッシュを生成してみましょう。

irbを起動して、以下のコードを順番に実行しましょう。

irb | 空のハッシュを生成する
1
{}
irb | キーと値の組み合わせを格納する
1
{ "name" => "田中 太郎" }
irb | 複数のキーと値の組み合わせを格納する
1
{ "name" => "田中 太郎", "age" => 18, "gender" => "男" }

上記をirbで実行すると、以下の画像のように生成されたハッシュが返ります。

出力結果

次は、ハッシュを変数に代入してみます。

ぴかわかさん

ハッシュを変数に代入

ハッシュはHashクラスのオブジェクトなので、変数に代入することができます。

ハッシュを変数に代入する
1
変数名 = ハッシュオブジェクト

ハッシュを変数に代入すると、以下の図のようにある1人のデータを管理するハッシュに対してuserと名付けることができます。

ハッシュを変数に代入

上の図をソースコードにする場合は、以下のように左辺に変数名、右辺にハッシュオブジェクトを指定します。

ハッシュを変数に代入する
1
user = { "name" => "田中 太郎", "age" => 18, "gender" => "男" }

ハッシュを変数に代入してみよう

irbを起動して、変数(user)に1人の情報をまとめたハッシュを代入してみましょう。

irb
1
user = { "name" => "田中 太郎", "age" => 18, "gender" => "男" }

ハッシュを変数に代入したら、動画のように変数名でハッシュを参照してみましょう。

ハッシュを参照する

userでハッシュオブジェクトを参照することができましたね。

次はハッシュの基本的な使い方を学ぶよ!

ぴかわかさん

ハッシュの基本的な使い方を学ぼう

ハッシュの基本的な使い方について学んでいきましょう。

ここからは、Rubyのファイルを使います。
hash.rbという名前のファイルを作成して、以下の内容を記述しておきましょう。

※ファイルは「pikawakaフォルダ」の直下に作成しましょう。

hash.rb
1
user = { "name" => "田中 太郎", "age" => 18, "gender" => "男" }

上記をCloud9のエディタに記述すると、警告マークが表示されます。

警告マーク

「定義した変数がエディタ上のどこにも使用されていない」という警告なので、現時点では気にする必要はありません。

それでは、「要素の参照・変更・追加・削除・繰り返し」を順番に学んでいきましょう。

要素の値を参照する

ハッシュから値を参照するには、以下のようにキーを指定します。

キーに対応する値を参照する
1
ハッシュ[キー]
サンプルコード
1
2
{ "name" => "田中 太郎" }["name"]
#=> "田中 太郎"

ただ、ハッシュは変数に代入して使いまわすことが多いので、上のような直接的な書き方はあまりしません。

変数を使う場合は、ハッシュを代入した変数名の後に[]でキーを指定します。

変数に代入した場合
1
2
変数名 = ハッシュ
ハッシュの変数名[キー]

前述の例で使用した図を使って、ハッシュの値の参照を確認してみましょう

変数userに代入したハッシュの値("田中 太郎")を参照するには、変数名だけではなくキー("name")を指定する必要があります。

キーを使用する

上の図をソースコードにすると、以下のようになります。

サンプルコード
1
2
3
4
user = { "name" => "田中 太郎", "age" => 18, "gender" => "男" }

user["name"] #変数名[キー]
#=> "田中 太郎"

user["name"]でキーである"name"に対応する"田中 太郎"が参照できます。

またハッシュを変数に代入することによって、user["name"]だけで「ユーザーの名前を参照している」と意味が伝わりますね。

それでは実際にhash.rbでキーの値を参照してみよう

ぴかわかさん

要素の値を参照してみよう

キーである"age"に対応する値の18を参照してみましょう。
hash.rbにハイライト箇所を記述してみましょう。

hash.rb
1
2
3
user = { "name" => "田中 太郎", "age" => 18, "gender" => "男" }

p user["age"]

続いて、動画のようにrubyコマンドhash.rbを実行してみましょう。

キーの値を参照する

実行すると、キーとして指定した"name"に対応付けられる18が出力されましたね。
このように各要素の値を参照するときは、[]と「キー」を使います。

要素の値を追加・変更する

ハッシュのキーと値を新しく追加するには、以下のように記述します。
新しく追加したキーと値は、ハッシュの最後に追加されます。

新しくキーと値を追加する
1
ハッシュ[キー] = 新しい値

例えば、身長が183という情報を追加する場合は、以下のようにキーを"height"に指定して右辺に新しく追加する値を記述します。

irb | 新しくキーと値を追加する場合
1
2
3
4
5
6
7
user = { "name" => "田中 太郎", "age" => 18, "gender" => "男" }

user["height"] = 183
#=> 183 user #=> {"name"=>"田中 太郎", "age"=>18, "gender"=>"男", "height"=>183}

userを実行すると、ハッシュの最後に"height"=>183が追加されていますね。

存在するキーを指定した場合は、値が上書きされます。

irb | 存在するキーの値を変更する場合
1
2
3
4
5
6
7
user = { "name" => "田中 太郎", "age" => 18, "gender" => "男" }

user["name"] = "佐藤 一郎"
#=>"佐藤 一郎" user #=> {"name"=>"佐藤 一郎", "age"=>18, "gender"=>"男"}

userには"name"というキーが既に存在しています。
そのため、上の例では"name"に対応する値が"田中 太郎"から"佐藤 一郎"に上書きされます。

実際にキーと値を追加・変更してみよう

ぴかわかさん

キーと値を新しく追加してみよう

まずはハッシュに新しくキーと値を追加してみましょう。

体重の情報として、キーである"weight"に対応する値の76を追加します。
hash.rbにハイライト箇所を記述してみましょう。

hash.rb | ハッシュに新しく値を追加する
1
2
3
4
5
user = { "name" => "田中 太郎", "age" => 18, "gender" => "男" }
p user
user["weight"] = 76
p user

続いて、動画のようにrubyコマンドでhash.rbを実行してみましょう。

ハッシュに新しく値を追加する

実行すると、ハッシュの最後に"weight" => "76"が追加されましたね。

キーの値を変更してみよう

次にハッシュの値を変更してみましょう。

キーである"age"を指定して、年齢を18から50に変更します。
ハイライトが当たる部分をhash.rbで編集してみましょう。

hash.rb | ハッシュの値を変更する
1
2
3
4
5
6
7
8
9
user = { "name" => "田中 太郎", "age" => 18, "gender" => "男" }
# p user
user["weight"] = 76
# p user
p user["age"]
user["age"] = 50
p user["age"]

続いて、動画のようにrubyコマンドでhash.rbを実行してみましょう。

ハッシュの値を変更する1

実行すると、"age"に対応する値が18から50に上書きされましたね。

ハッシュの値を変更する2

要素の値を削除する

ハッシュから値を削除するには、deleteメソッドを使います。
deleteメソッドの()内には削除する値のキーを指定します。

要素の値を削除する
1
ハッシュ.delete(キー)

例えば、ハッシュ内の"男"という値を削除する場合は、キーである"gender"をdeleteメソッドの()内に指定します。

irb | サンプルコード
1
2
3
4
5
6
7
user = { "name" => "田中 太郎", "age" => 18, "gender" => "男" }

user.delete("gender")
#=> gender

user
#=> {"name"=>"田中 太郎", "age"=>18}

要素の値を削除してみよう

それではdeleteメソッドを使って、ハッシュ内の値を削除してみましょう。

deleteメソッドにキーの"age"を指定して、年齢の情報を削除します。
ハイライトが当たる部分をhash.rbで編集してみましょう。

hash.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
user = { "name" => "田中 太郎", "age" => 18, "gender" => "男" }
# p user

user["weight"] = 76
# p user
# p user["age"]
user["age"] = 50
# p user["age"]
user.delete("age")
p user["age"]
p user

続いて、動画のようにrubyコマンドでhash.rbを実行してみましょう。

年齢の情報を削除する

存在しないキーを指定した場合は、nilが返ります。

deleteメソッドによって、"age"も含めて対応する値は削除されています。
そのため、削除後に参照しようとしても"age"は存在しないのでnilを返します。

要素分を繰り返す

ハッシュからキーと値を順番に取り出すには、eachメソッドを使います。

配列でもeachメソッドを使いましたが、ハッシュの場合はブロックの変数1に「キー」、変数2にキーに対応する「値」が順番に渡されます。

ブロック内ではキーと値が入った変数1変数2が使用できます。

ハッシュの繰り返し処理
1
2
3
ハッシュ.each do |変数1, 変数2|
  #繰り返したい処理
end

例えば、"キー : 値"のようにキーと値を文字列にして出力させます。
以下のようにブロック内で各変数(keyvalue)と式展開を利用します。

サンプルコード
1
2
3
4
5
6
7
8
9
user = { "name" => "田中 太郎", "age" => 18 }

user.each do |key, value|
p "#{key} : #{value}"
end #出力結果 "name : 田中 太郎" "age : 18"

eachメソッドによって、ハッシュにキーが追加された順番に取り出されます。

ソースコードだけでは少し難しいので、図を使って処理の流れを整理していきます。

ぴかわかさん

処理の流れを整理しよう

以下のサンプルコードの流れを図で1つ1つ説明します。

サンプルコード
1
2
3
4
5
user = { "name" => "田中 太郎", "age" => 18 }

user.each do |key, value|
p "#{key} : #{value}"
end

eachメソッドは、ハッシュにキーが追加された順番、つまりキーと値を最初から順番に取り出してブロックに渡します。

最初にハッシュ内の"name""田中 太郎"を取り出し、keyvalueに渡されます。

eachメソッドの動き

次に、ブロック内の処理が実行されます。

式展開の結果が出力されます。
このときブロック内のkeyvalueは、"name""田中 太郎"を参照します。

ブロック内の処理

ハッシュには要素がまだ存在するので、eachメソッドは次のキーと値("age"18)を取り出して、各変数に渡します。そして、同様にブロック内の処理が実行されます。

このときブロック内のkeyvalueは、"age"18を参照します。

次の要素を処理する

このように最後の要素になるまで、処理が繰り返されます。

実際にeachメソッドとブロックを使ってみよう!

ぴかわかさん

eachメソッドとブロックを使ってみよう

eachメソッドとブロックを使って、ハッシュの繰り返し処理を行いましょう。

ハイライが当たる箇所をhash.rbに書きましょう。

hash.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
user = { "name" => "田中 太郎", "age" => 18, "gender" => "男" }
# p user

user["weight"] = 76
# p user
# p user["age"]

user["age"] = 50
# p user["age"]

user.delete("age")
# p user["age"]
p user
user.each do |key, value|
p "キーは#{key}で、値は#{value}です。"
end

続いて、動画のようにrubyコマンドでhash.rbを実行してみましょう。

繰り返し処理

keyvalueには、ハッシュの中身が順番に渡されます。そのため、ブロック内の処理も先頭のキーと値から出力されます。

キーには「シンボル」を使う

ハッシュのキーには、これまで使用してきた文字列以外にも「任意のオブジェクト」を指定することができます。

文字列以外でキーとしてよく使われるのが、シンボルというオブジェクトです。
シンボルは「Symbolクラス」のオブジェクトで、セミコロン:を使います。

文字列とシンボルのクラス
1
2
3
4
5
"name".class
#=> String

:name.class
#=> Symbol

シンボルは文字列よりも実行の速度が速いのため、ハッシュのキーには文字列よりもシンボルが推奨されます。

ハッシュのキーにシンボルを使う

ハッシュのキーにシンボルを使うには、先頭にセミコロン:を付けます。
基本的には文字列のように扱うことができます。

キーが文字列の場合
1
{ "name" => "田中 太郎", "age" => 18 }
キーがシンボルの場合
1
{ :name => "田中 太郎", :age => 18 }

hash.rbの1行目にあるハッシュのキーを文字列からシンボルに変更してみましょう。

hash.rb | 変更前
1
2
3
user = { "name" => "田中 太郎", "age" => 18, "gender" => "男" }
# p user #省略...
hash.rb | 変更後
1
2
3
user = { :name => "田中 太郎", :age => 18, :gender => "男" }
# p user #省略...

シンボルを使って=>を省略する

ハッシュのキーにシンボルを使うと、=>を省略することができます。

=>を省略する場合は、シンボルのセミコロンの位置が変わります。
オブジェクトの「左側」に付くセミコロンは、オブジェクトの「右側」に付けます。

=>を省略しない場合 | シンボルのセミコロンはオブジェクトの左側に付ける
1
{ :name => "田中 太郎", :age => 18 }
=>を省略する場合 | シンボルのセミコロンはオブジェクトの右側に付ける
1
{ name: "田中 太郎", age: 18 }

「シンボル:」と「値」の間には、半角スペースを入れます。
セミコロンが左にある場合は、=>を省略することができないので注意してください。

それでは、hash.rbの1行目を変更して=>を削除してみましょう。

hash.rb | 変更前
1
2
3
user = { :name => "田中 太郎", :age => 18, :gender => "男" }
# p user #省略...
hash.rb | 変更後
1
2
3
user = { name: "田中 太郎", age: 18, gender: "男" }
# p user #省略...

続いて、コード変更後に正しく動作するかを確かめます。
動画のようにrubyコマンドでhash.rbを実行しましょう。

動作確認

エラーが発生することなく動作すれば、きちんと変更できています。

シンボルを使って値を参照する

ハッシュのキーがシンボルの場合は、以下のように指定して値を参照します。
[]の中のセミコロンは左にします。

シンボルを使った場合
1
ハッシュ[:シンボル]
サンプルコード
1
2
3
4
user =  { name: "田中 太郎", age: 18 }

user[:name]
#=> "田中 太郎"

以下のように指定することで、キーと値を新しく追加したり、キーが存在すれば上書きすることもできます。

シンボルを使った場合
1
ハッシュ[:シンボル] = 新しい値
サンプルコード
1
2
3
4
5
user = { name: "田中 太郎", age: 18 }

user[:name] = "山田 花子"
p user[:name]
#=> "山田 花子"

それでは、hash.rbを編集してみましょう。
ハッシュのキーが文字列になっている箇所は、全てシンボルに変えましょう。

変更前
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
user = { name: "田中 太郎", age: 18, gender: "男" }
# p user

user["weight"] = 76
# p user
# p user["age"]
user["age"] = 50
# p user["age"]
user.delete("age")
# p user["age"]
p user user.each do |key, value| p "キーは#{key}で、値は#{value}です。" end
変更後
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
user = { name: "田中 太郎", age: 18, gender: "男" }
# p user

user[:weight] = 76
# p user
# p user[:age]
user[:age] = 50
# p user[:age]
user.delete(:age)
# p user[:age]
p user user.each do |key, value| p "キーは#{key}で、値は#{value}です。" end

rubyコマンドでhash.rbを実行して、エラーが発生しなければ無事に変更することができています。

ハッシュのキーには、文字列ではなくシンボルを積極的に使いましょう

ぴかわかさん

ハッシュの応用的な使い方を学ぼう

入れ子構造のハッシュ

ハッシュの値には、これまで使用してきた文字列や数値以外にも「任意のオブジェクト」を指定することができます。

ハッシュは、Hashクラスのオブジェクトです。
そのため、ハッシュ自体もハッシュのキーに対応付けた値として格納することができます。

キーに対応付ける値としてハッシュを格納する
1
{ name: { last: "田中", first: "太郎" }, age: 18 }

ハッシュの{ last: "田中", first: "太郎" }は、name:のキーに対応付けた値として格納されています。

2次元ハッシュ

上の入れ子構造のハッシュのように、キーに対応付ける値として「別のハッシュ」を格納することができます。

入れ子構造のハッシュから値を参照するには、以下のように指定します。

入れ子構造のハッシュから値を参照する
1
ハッシュ[キー][入れ子のキー]
irb | サンプルコード
1
2
3
4
user = { name: { last: "田中", first: "太郎" }, age: 18 }

user[:name][:last]
#=> "田中"

指定するキーのシンボルは、どちらもセミコロンを左にします。

この記事のまとめ

  • ハッシュは、複数のオブジェクトへの参照をまとめて管理できる
  • ハッシュは、複数の名札が連結して自由に名前を付けられるイメージ
  • 複数の種類のオブジェクトを格納する場合は、配列よりもハッシュの方が識別しやすい