組み込みクラス: HashClass編
今日中にIOとTimeと正規表現がノルマ...
Hashの生成
ハッシュは通常の{key => value}
による定義以外にも、配列のようなHash[key,value]
が使える。
irb(main):001:0> a = Hash[:tokyo, "新宿",:kanagawa,"横浜",:ehime,"matsuyama"] => {:tokyo=>"新宿", :kanagawa=>"横浜", :ehime=>"matsuyama"}
Hash.newに引数をわたして、デフォルト値を設定しておくこともできる。
irb(main):002:0> a = Hash.new("default") => {} irb(main):003:0> a[:tokyo] => "default"
Hash.newはブロックをとることもできるので、そこでデフォルト値を設定する方法もある。
irb(main):004:0> c = Hash.new{|hash,key| hash[key] = "default"} => {} irb(main):005:0> c[:tokyo] => "default"
ハッシュオブジェクトを作ったあとで、default
メソッドで指定する方法もある。
irb(main):006:0> x = Hash.new() => {} irb(main):007:0> x[:tokyo] => nil irb(main):008:0> x.default = "DEFAULT" => "DEFAULT" irb(main):009:0> x[:tokyo] => "DEFAULT"
ハッシュのキーや値を取得する
keys,values
それぞれ、ハッシュのキー一覧と値一覧を配列で返す。
irb(main):013:0> a = Hash[:tokyo, "新宿",:kanagawa,"横浜",:ehime,"松島"] => {:tokyo=>"新宿", :kanagawa=>"横浜", :ehime=>"松島"} irb(main):014:0> a.keys => [:tokyo, :kanagawa, :ehime] irb(main):015:0> a.values => ["新宿", "横浜", "松島"]
values_at
キーをメソッドの可変数引数として渡して、その値を配列で受け取る。
irb(main):016:0> a.values_at(:tokyo,:kanagawa) => ["新宿", "横浜"]
fetch
配列でも扱ったように、fetchは存在しないキーを指定するとエラーを起こす。 これを回避するには、2番目の引数を指定しておくか、ブロックで処理を決めておく。
irb(main):018:0> a.fetch(:oosaka,"なかった。") => "なかった。" irb(main):019:0> a.fetch(:oosaka){p "ないよ"} "ないよ" => "ないよ"
select
ブロックを指定して、各ハッシュの要素(or キー)がtrueになったものだけを含んだ、ハッシュを返す。
irb(main):020:0> a = Hash[:tokyo, "新宿",:kanagawa,"横浜",:ehime,"松島", :fukuoka, "博多", :hokkaido, "札幌"] => {:tokyo=>"新宿", :kanagawa=>"横浜", :ehime=>"松島", :fukuoka=>"博多", :hokkaido=>"札幌"} irb(main):021:0> a.select{|key,value| key.to_s.length > 6} => {:kanagawa=>"横浜", :fukuoka=>"博多", :hokkaido=>"札幌"}
find_all
selectの返り値が配列になったバージョン。
irb(main):022:0> a.find_all{|key,value| key.to_s.length > 6} => [[:kanagawa, "横浜"], [:fukuoka, "博多"], [:hokkaido, "札幌"]]
ハッシュを変更する
delete破壊的
ハッシュのキーを指定して削除する。
reject 破壊的あり
破壊的メソッドreject!
のエイリアスはdelete_if
である。
値を指定して削除する直接の方法はなく、reject
でブロックで渡しながら削除する値を選ぶことになる。
irb(main):023:0> a => {:tokyo=>"新宿", :kanagawa=>"横浜", :ehime=>"松島", :fukuoka=>"博多", :hokkaido=>"札幌"} irb(main):024:0> a.delete_if{|key,value| value == "横浜"} => {:tokyo=>"新宿", :ehime=>"松島", :fukuoka=>"博多", :hokkaido=>"札幌"}
replace,clear 破壊的
Arrayと同じく丸ごと置きかえ・全削除
shift 破壊的
配列でもshifはpopやinsertと同じく破壊的なメソッドであるように、shiftは破壊的メソッドとして用意されている
irb(main):025:0> a.shift => [:tokyo, "新宿"] irb(main):026:0> a => {:ehime=>"松島", :fukuoka=>"博多", :hokkaido=>"札幌"}
merge 破壊的あり
他のハッシュをマージする。破壊的メソッドmerge!
のエイリアスとしてupdate
が用意されている。
重複するキーに対応するため、ブロックを渡して、どちらをバリューとして選ぶか選択することが可能になっている。
instance method Hash#merge (Ruby 2.6.0)
irb(main):026:0> a => {:ehime=>"松島", :fukuoka=>"博多", :hokkaido=>"札幌"} irb(main):027:0> a.merge({:ehime => "宇和島", :hokkaido => "hakodate"}){|key,self_val,new_val| new_val} => {:ehime=>"宇和島", :fukuoka=>"博多", :hokkaido=>"hakodate"} irb(main):028:0> a.merge({:ehime => "宇和島", :hokkaido => "hakodate"}){|key,self_val,new_val| self_val} => {:ehime=>"松島", :fukuoka=>"博多", :hokkaido=>"札幌"}
invert破壊的なし
キーとハッシュのいれかえ。破壊的メソッドが存在しない。
irb(main):028:0> a.merge({:ehime => "宇和島", :hokkaido => "hakodate"}){|key,self_val,new_val| self_val} => {:ehime=>"松島", :fukuoka=>"博多", :hokkaido=>"札幌"} irb(main):029:0> a.invert => {"松島"=>:ehime, "博多"=>:fukuoka, "札幌"=>:hokkaido} irb(main):030:0> a => {:ehime=>"松島", :fukuoka=>"博多", :hokkaido=>"札幌"} irb(main):031:0> a.invert! Traceback (most recent call last): 2: from /home/pyons/.rbenv/versions/2.5.0/bin/irb:11:in `<main>' 1: from (irb):31 NoMethodError (undefined method `invert!' for {:ehime=>"松島", :fukuoka=>"博多", :hokkaido=>"札幌"}:Hash Did you mean? invert)
ハッシュを調べる
key?
なぜか3つもエイリアスが存在する謎メソッド。 include?, member? (Hash) - Rubyリファレンス
キーが存在するか調べる。booleanの返り値。
has_key?
とinclude?
とmemeber?
がエイリアス。
value?
has_value
がエイリアス。
値が存在するか調べる。
each_pair 破壊的なし
ブロックにkeyとvalueを渡していき、ブロック内で処理を行う。each
がエイリアスである。
因みにブロック内で代入をおこなって値を変えようとしても、変更は起こらない。
irb(main):036:0> a.each{|k,v| v = "観光地"} => {:ehime=>"松島", :fukuoka=>"博多", :hokkaido=>"札幌"} irb(main):037:0> a => {:ehime=>"松島", :fukuoka=>"博多", :hokkaido=>"札幌"}
each_key, each_value
irb(main):034:0> a.each_key{|key|p key} :ehime :fukuoka :hokkaido => {:ehime=>"松島", :fukuoka=>"博多", :hokkaido=>"札幌"} irb(main):035:0> a.each_value{|key|p key} "松島" "博多" "札幌"
配列に変換
to_a
HashはStringと異なり、配列に変換するメソッドが用意されている。
sort 破壊的なし
配列にしてソートする。また、ブロックに渡して、手動バブルソートも行える。 Arrayと異なり、返り値が同じ型でなくなってしまうため破壊的なメソッドがない。
irb(main):040:0> a => {:ehime=>"松島", :fukuoka=>"博多", :hokkaido=>"札幌"} irb(main):041:0> a.sort! Traceback (most recent call last): 2: from /home/pyons/.rbenv/versions/2.5.0/bin/irb:11:in `<main>' 1: from (irb):41 NoMethodError (undefined method `sort!' for {:ehime=>"松島", :fukuoka=>"博多", :hokkaido=>"札幌"}:Hash Did you mean? sort)