【Ruby】Lesson4-8|ハッシュでキーと値のデータを管理しよう

ながみえ

一つ前のページではfilterメソッドについて学習しました。

今回は ハッシュ について見ていきましょう。

Lesson1:基礎文法編
Lesson2:制御構造編
Lesson3:メソッド
Lesson4:コレクション

 ・Lesson4-1:配列の基本を理解しよう
 ・Lesson4-2:配列を操作しよう
 ・Lesson4-3:配列を調査しよう
 ・Lesson4-4:配列を並び替えよう
 ・Lesson4-5:eachメソッドを理解しよう
 ・Lesson4-6:mapメソッドを理解しよう
 ・Lesson4-7:filterメソッドを理解しよう
 ・Lesson4-8:ハッシュを理解しよう ◁今回はココ
 ・確認問題4-☆1:ナインゲームを作ろう
 ・確認問題4-☆2:アラビア数字をローマ数字に変換しよう
 ・確認問題4-☆3:トランプをランダムに配ろう
Lesson5:オブジェクト指向編

<<前のページ

Rubyの記事一覧

次のページ>>

ハッシュ入門|キーと値で柔軟なデータ構造を作ろう

ハッシュ とは、データを「キー」と「値」のペアで管理するデータ構造です。

配列がインデックス(番号)を使って値を管理するのに対し、ハッシュは任意のキーを使って値を参照できます。

そのためデータの意味をわかりやすく管理したい場合に便利です。

例えばユーザーの情報を管理する場合、名前や年齢などのデータに適切なラベル(キー)を付けて保存できます。

ハッシュの基本構文と定義方法|シンボルとは何か

たとえば、以下のようにキーと値が対応するデータ構造を作成したいとします。

ハッシュのキーハッシュの値
名前:nameTaro
年齢:age25
住所:cityTokyo

配列では、それぞれのリストは作れても「名前:Taro」や「年齢:25」のように対応するデータにはなりません。

そこでハッシュを使用します。

数値や文字列をキーとする書き方

user = { "name" => "Taro", "age" => 25, "city" => "Tokyo" }

ここでnameagecity がキーで、"Taro"25"Tokyo" がそれぞれの値です。

ハッシュは中括弧 {} を使って定義します。キーと値はコロン : で区切り、ペアごとにカンマ , で区切ります。

これにより、キーと値が対応するデータ構造が作成できました。

ただし、この書き方は現在のRubyではあまり一般的ではありません。

シンボルをキーとする書き方|文字列との違い

キーには数値や文字列ではなく シンボル を使用する書き方が推奨されます。

例えば以下のコードは、先ほどの文字列をキーとしたコードと全く同じ意味になります。

user = {name: "Taro", age: 25, city: "Tokyo" }

シンボルとは、ラベル(名前)を表す軽量なオブジェクトであり、文字列の前に「:」を書いて定義します。

文字列と似ていますが、変更できない・同じ名前なら同一オブジェクトという特徴があります。

例えば変数「name」とシンボル「:name」は以下のような違いがあります。

項目シンボル :name文字列 "name"
オブジェクトID常に同じ都度異なる
変更できないできる
メモリ効率良い(1つだけ)普通(たくさん作れる)
用途ラベル/識別子文章データなど

そして、シンボルと値のセット( = ハッシュ)として使用する際には、「:」を文字列の後ろに記載します。

  • :name … 「ただのラベル(名前)」として使いたい時の書き方
  • name: … 「ここあとに値がくる」というハッシュの記述方法

ハッシュの操作方法|データの取り出し・追加・更新・削除

ハッシュにデータを追加したり更新したりするのは簡単です。

以下にいくつかの操作例を示します。

値の取得

キーを指定して値を取得します。

user = { name: "John", age: 25 } # ハッシュuserの定義
puts user[:name]				 # ハッシュuser内のキー「:name」に対応する値を取り出して出力
								 # => Jhon

値の追加と更新

新しいキーと値を追加するか、既存のキーを更新できます。

user = { name: "John", age: 25 } # ハッシュuserの定義
user[:city] = "Tokyo"		 	# ハッシュuserに新しいキーと値を追加
user[:age] = 30		 			# ハッシュuser内のキー「:name」に対応する値を30に変更

p user		 				 	# => {:name=>"John", :age=>30, :city=>"Tokyo"}

deleteメソッドによる値の削除

delete メソッドを使うと特定のキーと値を削除できます。

user = { name: "John", age: 25 } # ハッシュuserの定義
user.delete(:age)				 # ハッシュuser内のキー「:age」に対応する値を削除

p user		 				 	# => {:name=>"John"}

よく使うハッシュメソッド一覧

Rubyのハッシュには多くの便利なメソッドが用意されています。

ここでは主要なメソッドを紹介します。

要素数取得|lengthメソッド と sizeメソッド

ハッシュの要素数を取得します。どちらも同じ結果を返します。

user = { name: "John", age: 25 }
puts user.length  # 結果: 2
puts user.size    # 結果: 2

キーや値の取得|keysメソッド と valuesメソッド

キーだけ、または値だけを取得します。

user = { name: "John", age: 25 }
puts user.keys    # 結果: [:name, :age]
puts user.values  # 結果: ["John", 25]

特定のキーや値の有無確認|key?メソッド と value?メソッド

指定したキーや値が存在するか確認します。

user = { name: "John", age: 25 }
puts user.key?(:name)	 # 結果: true
puts user.key?(:city)	 # 結果: false
puts user.value?(25)	 # 結果: True
puts user.value?("Taro") # 結果: false

まとめ|ハッシュの活用ポイント

Rubyのハッシュはデータを整理して管理するのに非常に便利なデータ構造です。

キーと値のペアを使うことで、コードがより読みやすく意味のあるものになります。

これを活用してアプリケーションのデータ構造を効率的に構築しましょう!

練習問題|ハッシュを使って学生の成績を集計しよう

ハッシュを使った成績カウントの実践課題

学生の成績データをハッシュを使って管理し、それぞれの成績ごとに何人の学生がいるかをカウントするプログラムを作成しましょう。

このプログラムでは、複数の学生の成績を集計し、結果を表示します。

成績データはハッシュとして以下のように与えられます。

students = { "田中" => "A", "佐藤" => "B", "鈴木" => "A", "高橋" => "C", "伊藤" => "B", "渡辺" => "A" }

以下の要件に従ってコードを完成させてください。

  • 学生の名前と成績を管理するハッシュ students を定義し、複数の学生の名前と成績を格納すること。
  • ハッシュ students を使って、それぞれの成績をカウントし、grade_count ハッシュに格納すること。
  • each メソッドを使って、students ハッシュの各要素を繰り返し処理すること。
  • 最後に、grade_count ハッシュに基づいて、それぞれの成績の学生数を表示すること。

ただし、以下のような実行結果となること。

成績A: 3人
成績B: 2人
成績C: 1人

【ヒント】自力で解くのが難しい人へ

1からコードを組み立てることが難しい場合は、以下のヒントを開いて参考にしましょう。

Q
ヒント1【コードの構成を見る】

正解のコードは上から順に以下のような構成となっています。
(※下記の□はコード内のインデントを表しています)

1:studentsハッシュを初期化し、各学生の名前と成績を格納
2:grade_countハッシュを初期化し、各成績のカウントを保存する準備
3:studentsハッシュの各要素に対して繰り返し処理を実行
  □ name変数にキー(名前)、grade変数に値(成績)を代入
  □ if文でgrade_countハッシュにgradeキーが存在するかを判定
  □ □ gradeキーが存在する場合、値を1増加
  □ □ gradeキーが存在しない場合、新たにキーを作成し値を1に設定
4:grade_countハッシュの各要素に対して繰り返し処理を実行
  □ grade変数にキー(成績)、count変数に値(人数)を代入
  □ 成績と人数を文字列に整形して出力

Q
ヒント2【穴埋め問題にする】

以下のコードをコピーし、コメントに従ってコードを完成させて下さい。

# 学生の成績データ
students = { "田中" => "A", "佐藤" => "B", "鈴木" => "A", "高橋" => "C", "伊藤" => "B", "渡辺" => "A" }

# 各成績のカウントを格納するためのハッシュ
grade_count = {}

# ハッシュ内の各成績をカウント
students.each do |name, grade|
=begin 【穴埋め問題1】
  ここに、すでにその成績がカウントされているかを確認し、カウントを増やすか新しいカウントを開始するコードを書いてください。
=end
end

# 各成績の学生の数を表示
grade_count.each do |grade, count|
=begin 【穴埋め問題2】
  ここに、成績とそれに対応する学生の人数を表示するコードを書いてください。
=end
end

このヒントを見てもまだ回答を導き出すのが難しいと感じる場合は、先に正解のコードと解説を見て内容を理解するようにしましょう。

この問題の解答例と解説

この問題の正解コードとその解説は以下の通りです。

クリックして開いて確認してください。

Q
正解コード
# 学生の成績データ
students = { "田中" => "A", "佐藤" => "B", "鈴木" => "A", "高橋" => "C", "伊藤" => "B", "渡辺" => "A" }

# 各成績のカウントを格納するためのハッシュ
grade_count = {}

# ハッシュ内の各成績をカウント
students.each do |name, grade|
  if grade_count[grade]
    # すでにその成績がカウントされている場合は、カウントを増やす
    grade_count[grade] += 1
  else
    # 初めて出現した成績の場合は、カウントを1にする
    grade_count[grade] = 1
  end
end

# 各成績の学生の数を表示
grade_count.each do |grade, count|
  puts "成績#{grade}: #{count}人"
end
Q
正解コードの解説

コードをブロックごとに分割して解説します。

ハッシュの定義

students = { "田中" => "A", "佐藤" => "B", "鈴木" => "A", "高橋" => "C", "伊藤" => "B", "渡辺" => "A" }

ここではstudents という名前のハッシュを定義しています。ハッシュでは、キーと値をセットで管理します。

この場合キーは学生の名前で、値はその学生の成績です。

空のハッシュの作成

grade_count = {}

grade_count という空のハッシュを定義しています。

このハッシュは各成績(A, B, Cなど)が何回出現したかをカウントするために使います。

ハッシュの要素を繰り返し処理

students.each do |name, grade|
  if grade_count[grade]
    grade_count[grade] += 1
  else
    grade_count[grade] = 1
  end
end

この部分ではstudents ハッシュを each メソッドで繰り返し処理しています。

name には学生の名前、grade には成績が格納され、それぞれの成績を grade_count ハッシュでカウントします。

if 文: ここですでに grade_count にその成績が登録されているかをチェックしています。

もし成績がすでに存在していればカウントを1増やし、存在しない場合は初めてその成績が出現したとしてカウントを1に設定します。

結果の表示

grade_count.each do |grade, count|
  puts "成績#{grade}: #{count}人"
end

最後にgrade_count ハッシュを使って、それぞれの成績の学生数を表示しています。

each メソッドを使って、キー(成績)と値(人数)を一つずつ取り出し、puts で表示しています。

まとめ

このプログラムでは、ハッシュ を使って成績データを効率的に集計しています。

ハッシュは、複数のデータをキーと値で管理し、特定のキーに関連する値を簡単に操作することができる非常に便利なデータ構造です。

もっと分かりやすいサイトにするために

この記事を読んで「ここが分かりにくかった」「ここが難しかった」等の意見を募集しています。

世界一わかりやすいRuby学習サイトにするため、ぜひ 問い合わせフォーム からご意見下さい。

<<前のページ

Rubyの記事一覧

次のページ>>

FAQ|Rubyのハッシュの使い方と疑問解消

Q
Q1. Rubyでハッシュのキーにはシンボルと文字列のどちらを使うべきですか?

処理速度やメモリ効率を重視する場合は、シンボル(例::name)の使用が推奨されます。シンボルは一度生成されると再利用されるため、文字列よりも軽量で高速です。ただし、外部から動的にキーが渡る場合などには文字列を使う場面もあります。

Q
Q2. Hash#key? と Hash#has_key? の違いはありますか?

key?has_key? のエイリアスで、機能的な違いはありません。ただし、key? の方が短くモダンな書き方とされるため、可読性を意識して key? の使用が一般的です。

Q
Q3. Rubyのハッシュにおいて順序は保持されますか?

Ruby 1.9以降、ハッシュは定義された順序を保持するようになりました。これは、each などでキーを取り出す際に順序が維持されることを意味し、意図した順番でデータを扱えるため便利です。

記事URLをコピーしました