Ruby基礎復習(6) Hash
『パーフェクトRuby』p.179より。
まず基本的なとこで。
hash = {hoge: 1, fuga: 2}
hash.each do |key, val|
p "#{key}: #{val}"
end # => "hoge: 1", "fuga: 2"
hash.each_key do |key|
p key
end # => "hoge", "fuga"
hash.each_value do |val|
p val
end # => "1", "2"
hash[:hoge] = 3
p hash # => {hoge: 3, fuga: 2}
hash[:piyo] = 4
p hash # => {hoge: 3, fuga: 2, piyo: 4}
hash.delete(:piyo)
hash # => {hoge: 3, fuga: 2}
hash.empty? # => false
hash.length # => 2
ハッシュの生成はHash[]
により偶数個の引数から行うこともできる。
ary = ["hoge", 1, "fuga", 2]
Hash[*ary] # => {hoge: 1, fuga: 2}
ary = [["hoge", 1], ["fuga", 2]]
Hash[ary] # => {hoge: 1, fuga: 2}
Arrayクラスと同様の#select
、#reject
、#keep_if
、#delete_if
操作が可能。
hash = {hoge: 1, fuga: 2, piyo: 3}
hash.select {|key, val| val.even? } # => {fuga: 2}
p hash # => {hoge: 1, fuga: 2, piyo: 3}
hash.select! {|key, val| val.even? } # => {fuga: 2}
p hash # => {fuga: 2}
hash = {hoge: 1, fuga: 2, piyo: 3}
hash.reject {|key, val| val.even? } # => {hoge: 1, piyo: 3}
p hash # => {hoge: 1, fuga: 2, piyo: 3}
hash.reject! {|key, val| val.even? } # => {hoge: 1, piyo: 3}
p hash # => {hoge: 1, piyo: 3}
hash.select! {|key, val| val.even? } # => nil
hash.keep_if {|key, val| val.even? } # => {hoge: 1, piyo: 3}
hash.reject! {|key, val| val.even? } # => nil
hash.delete_if {|key, val| val.even? } # => {hoge: 1, piyo: 3}
Hashの統合はHash#merge
を用いる。キーが重複する場合は、引数で渡されたハッシュの値で上書きされる。ブロックを引き渡している場合は、キー重複時の処理をブロックの中で定義できる。破壊的操作であるHash#merge!
はHash#update
とも書くことが出来る。
a = {hoge: 1, fuga: 2}
b = {hoge: 3, piyo: 4}
a.merge(b) # => {hoge: 3, fuga: 2, piyo: 4}
p a # => {hoge: 1, fuga: 2}
a.merge!(b) {|key, a_val, b_val|
a_val + b_val
} # => {hoge: 4, fuga: 2, piyo: 4}
p a # => {hoge: 4, fuga: 2, piyo: 4}
キーと値の取得に関して。特に特定キーの存在確認については、Hash#has_key?
を用いる。通常のHash[]
による呼び出しだと、値が存在しない場合でもnilが返ってきてしまい、値がnilなのか、それとも存在していないのか区別がつかないため。あるいはHash#fetch
を用いれば、値が存在しない場合の返り値を指定できる。
hash = {hoge: 1, fuga: 2, piyo: 3, hogehoge: nil}
hash.keys # => [:hoge, :fuga, :piyo]
hash.key(2) # => :fuga
hash.values # => [1, 2, 3]
hash.values_at(:fuga) # => [2]
hash.values_at(:fuga, :piyo) # => [2, 3]
hash[:hogehoge] # => nil
hash[:foo] # => nil
hash.has_key?(:foo) # => false
# 以下すべてhas_key?と同義
hash.member?(:foo)
hash.include?(:foo)
hash.key?(:foo)
hash.fetch(:foo) # => nil
hash.fetch(:foo, "error") # => "error"
hash.fetch(:foo){|key| "#{key} not exists"} # => "foo not exists"
hash.has_value?(3) # => true
hash.value?(3) # => true
Hashにはデフォルト値の概念があり、Hash#new
の引数に与えた値が、存在しないキーを参照したときの返り値となる(デフォルトはnil)。ここで指定した値はすべて同一オブジェクトであり、破壊的操作をする場合などは注意が必要。またHash#default=
やHash#default_proc=
により、既存のHashオブジェクトに対してもデフォルト値の変更が可能。
hash = Hash.new("null")
hash[:foo] # => "null"
hash.default = "undefined"
hash[:foo] # => "undefined"
default = hash.default
default.reverse!
hash[:foo] # => "denifednu"
hash.default_proc = ->(hash, key) {"Key: #{key} not exists"}
hash[:foo] # => "Key: foo not exists"
ハッシュ変換系のメソッド。
hash = {hoge: 1, fuga: 2}
hash.invert # => {1: hoge, 2: fuga}
hash.to_a # => [[:hoge, 1], [:fuga, 2]]
hash.sort # => [[:fuga, 2], [:hoge, 1]]