ハッシュ

ハッシュとは

身の回りにあるものや人には様々な性質が備わっている。 そのような性質を記す方法は様々なところで用いられている。

特定のキャラクタに対する属性を管理する場合を考える。 たとえば以下の一覧にあるものを表現したい。

[0]
donapon
名前ドナポン
属性
最大MP250
初期MP20
[1]
lageyen
名前ラジャイン
属性
最大MP450
初期MP2
[2]
liztang
名前リッタン
属性
最大MP150
初期MP30
[3]
otoske
名前音助
属性
最大MP100
初期MP80

図: キャラクタ集の例

上記の最初のキャラクタの場合、

という関係性を持つ。このように、特定のキーワードに対応する値を持つ 関係性の集合をハッシュといいう。 ここで、各関係の左辺にある元となるキーワードのことをキー(key)、 右辺にある対応値のことをバリュー(value)という。 上の例では以下のようになる。

キーバリュー
"名前""ドナポン"
"属性""甘"
"最大MP"250
"初期MP"20

Rubyでのハッシュ表現

Rubyではこの対応関係を

{キー1 => バリュー1, キー2 => バリュー2, ...}

の形式で表す。上のキャラクタ例は以下のように表現する(値の部分の文字列と数値の違いに注意)。

{"名前" => "ドナポン", "属性" => "甘", "最大MP" => 250, "初期MP" => 20}

この値を何らかの変数に入れて処理することになる。 変数aに入れて、「名前」に対応する値を取り出すには以下のようにする(実際にirbで試してみること)。

irb
a = {"名前" => "ドナポン", "属性" => "甘", "最大MP" => 250, "初期MP" => 20}
a["名前"]
=> "ドナポン"

このように、ハッシュを持っている変数にキーを添え字に指定すると バリューを取り出せる。

逆に、値を設定するときは添字付きで代入する。

a["最大MP"] = 350
=> 350
a
=> {"名前"=>"ドナポン", "属性"=>"甘", "最大MP"=>350, "初期MP"=>20}

ハッシュオブジェクト

ハッシュ形式の値はプログラムを書くときに定まるものだけではない。 たとえば以下のような新キャラクタを、プログラム実行後に利用者に 好きな値を入力して決めてよいことにしたい場合を考える。

[3]
New Character
名前???
属性???
最大MP???
初期MP???

このような場合は、キーとバリューのペアを一つも持っていない 空のハッシュ値 を入れてから代入させる。

newchar = {}		# {} が空のハッシュ値
print "名前は何にしますか?: "
newchar["名前"] = gets.chomp
print "属性は何にしますか?: "
newchar["属性"] = gets.chomp
print "最大MPはいくつにしますか?: "
newchar["最大MP"] = gets.to_i
print "初期MPはいくつにしますか?: "
newchar["初期MP"] = gets.to_i

空のハッシュ値は Hash.new でも生成できる。

newchar = Hash.new		# newchar = {} と同じ

ハッシュ形式の値のことをハッシュオブジェクトといい、 Hash.new で空のハッシュオブジェクトが生成できる。

newchar.rb

#!/usr/koeki/bin/ruby
# -*- coding: utf-8 -*-
newchar = Hash.new			# newchar = {} と同じ
print "名前は何にしますか?: "
newchar["名前"] = gets.chomp
print "属性は何にしますか?: "
newchar["属性"] = gets.chomp
print "最大MPはいくつにしますか?: "
newchar["最大MP"] = gets.to_i
print "初期MPはいくつにしますか?: "
newchar["初期MP"] = gets.to_i
puts newchar

newchar.rbを保存して動かしてみよ。

./newchar.rb
名前は何にしますか?: たむどん
属性は何にしますか?: 沼
最大MPはいくつにしますか?: 999
初期MPはいくつにしますか?: 10
{"名前"=>"たむどん", "属性"=>"沼", "最大MP"=>999, "初期MP"=>10}

問題1

  1. 図1の[1]のキャラクタのもつ性質を ハッシュで表し、変数bに代入する文を書け。
  2. 図1の[2]のキャラクタのもつ性質を ハッシュで表し、変数cに代入する文を書け。
  3. 山形県に関して、「都道府県名」「県庁所在地」「人口」を キーとするハッシュを作り、変数ymgtに代入する文を書け。 irbで実行して確認すること。
  4. 秋田県に関して、「都道府県名」「県庁所在地」「人口」を キーとするハッシュを作り、変数aktに代入する文を書け。 irbで実行して確認すること。

※都道府県ごとの人口は 総務省:住民基本台帳に基づく人口、人口動態及び世帯数 の「住民基本台帳人口・世帯数、令和4年人口動態(都道府県別)」 などを参考にするとよい。

ハッシュ値の集合

ハッシュ値は一つの個体の性質の集合を表すことができる。 一般的には個体が複数存在するので、これらを配列の形で表現することが多い。

図1の[0]から[3]の4つのキャラクタは 以下のようにハッシュ表現できる。

# [0]
{"名前" => "ドナポン", "属性" => "甘", "最大MP" => 250, "初期MP" => 20}
# [1]
{"名前" => "ラジャイン", "属性" => "土", "最大MP" => 450, "初期MP" => 2}
# [2]
{"名前" => "リッタン", "属性" => "沼", "最大MP" => 150, "初期MP" => 30}
# [3]
{"名前" => "音助", "属性" => "波", "最大MP" => 100, "初期MP" => 80}

4つの各値を要素とする配列にする。つまり、

[ハッシュ値1, ハッシュ値2, ハッシュ値3, ハッシュ値1]

の形式で並べると以下のようになる。

[
 {"名前" => "ドナポン", "属性" => "甘", "最大MP" => 250, "初期MP" => 20},  # ←カンマに注意
 {"名前" => "ラジャイン", "属性" => "土", "最大MP" => 450, "初期MP" => 2},
 {"名前" => "リッタン", "属性" => "沼", "最大MP" => 150, "初期MP" => 30},
 {"名前" => "音助", "属性" => "波", "最大MP" => 100, "初期MP" => 80}
]

変数に代入して、個別にアクセスしてみる。irbで以下を実行してみよ。

irb
chara = [
 {"名前" => "ドナポン", "属性" => "甘", "最大MP" => 250, "初期MP" => 20},
 {"名前" => "ラジャイン", "属性" => "土", "最大MP" => 450, "初期MP" => 2},
 {"名前" => "リッタン", "属性" => "沼", "最大MP" => 150, "初期MP" => 30},
 {"名前" => "音助", "属性" => "波", "最大MP" => 100, "初期MP" => 80}
]
chara
=>
[{"名前"=>"ドナポン", "属性"=>"甘", "最大MP"=>250, "初期MP"=>20},
 {"名前"=>"ラジャイン", "属性"=>"土", "最大MP"=>450, "初期MP"=>2},
 {"名前"=>"リッタン", "属性"=>"沼", "最大MP"=>150, "初期MP"=>30},
 {"名前"=>"音助", "属性"=>"波", "最大MP"=>100, "初期MP"=>80}]
# 先頭要素[0]を取り出す
chara[0]
=> {"名前"=>"ドナポン", "属性"=>"甘", "最大MP"=>250, "初期MP"=>20}
# 4番目[3]を取り出す
chara[3]
=> {"名前"=>"音助", "属性"=>"波", "最大MP"=>100, "初期MP"=>80}
# 4番目[3]の名前を取り出す
chara[3]["名前"]
=>"音助"
# 4番目[3]の初期MPを上書きして90に更新する
chara[3]["初期MP"]=90
=> 90
chara[3]
=> {"名前"=>"音助", "属性"=>"波", "最大MP"=>100, "初期MP"=>90}

この(chara)配列に、新たなキャラクタのハッシュ値を追加する 例を示す。charaは配列なので要素として追加する。

chara << {"名前"=>"ハテナ", "属性"=>"謎", "最大MP"=>400, "初期MP"=>0}
=>
[{"名前"=>"ドナポン", "属性"=>"甘", "最大MP"=>250, "初期MP"=>20},
 {"名前"=>"ラジャイン", "属性"=>"土", "最大MP"=>450, "初期MP"=>2},
 {"名前"=>"リッタン", "属性"=>"沼", "最大MP"=>150, "初期MP"=>30},
 {"名前"=>"音助", "属性"=>"波", "最大MP"=>100, "初期MP"=>90},
 {"名前"=>"ハテナ", "属性"=>"謎", "最大MP"=>400, "初期MP"=>0}]

5個目(第4)要素が増えた。

問題

  1. ある八百屋にあった3品目の単価リスト:

    りんご:150 みかん:30 いちご:20

    をハッシュ形式で表現し、それを変数yaoyaに 代入する文を書け(答は何通りもある)。

  2. 1のyaoya変数に「梨:120」を表現する値を代入する 文を書け(答は何通りもある)。

  3. 東北6県の各県について「都道府県名」「県庁所在地」「人口」を キーとするハッシュを作り、それらを6要素の配列としたものを変数 tohoku に代入する文を書け。


本日の目次