ruby - Hello world! と基本的な文法 - Hash 連想配列

 
1. Hash 連想配列
2. 初期化
3. 追加
4. 全件アクセス
5. キーを持っているか has_key?
6. 削除

1. Hash 連想配列

 連想配列ってのは、この手の言語では必ず出現する便利な奴ですな。  連想配列に関しては、以下に詳しく述べられています。
Ruby リファレンス - 標準クラス・モジュール > HashRuby 2.5.0 リファレンスマニュアル > ライブラリ一覧 > 組み込みライブラリ > Hash クラス 

2. 初期化

 要素つきの初期化を行うには、まず、次の4つのいずれか。  この4つは同じ意味を持ちます。

hash = Hash[ 'foo' => 'bar', 'hoge' => 'fuga' ]
hash = Hash[ :foo => 'bar', :hoge => 'fuga' ]
hash = { 'foo' => 'bar', 'hoge' => 'fuga' }
hash = { :foo => 'bar', :hoge => 'fuga' }
 Hash.new で要素をいれることができるようですが、使い方が難しくてよくわかりません。  : と '' の使い分けはまだわかっていません。  キーと値を区別するには : の方がいいのかしらん。  メンバなしの初期化は、次の3つのいずれか。

hash = {}
hash = Hash[]
hash = Hash.new

3. 追加

 要素を追加するには、以下のいずれかの構文を使います。

hash[:foo]   = 'bar'
hash['hoge'] = 'fuga'

4. 全件アクセス

 全件アクセスするには each(キーと値を取得)、each_key(キーを取得)、each_value(値を取得)を使います。
hash = { :foo => 'bar', :hoge => 'fuga' }

# |(パイプライン)で囲む

hash.each { | key, value |
    puts "[#{__LINE__}] key = #{key}  value = #{value}"
}

hash.each_key { | key |
    puts("[#{__LINE__}] key = #{key} ")
}

hash.each_value { | value |
    puts("[#{__LINE__}] value = #{value}")
}

# do ~ end で囲む

hash.each do | key, value |
    puts "[#{__LINE__}] key = #{key}  value = #{value}"
end

hash.each_key do | key |
    puts("[#{__LINE__}] key = #{key} ")
end

hash.each_value do | value |
    puts("[#{__LINE__}] value = #{value}")
end


 値となる変数を囲んだ |値| の後ろの |(パイプライン)までは、Array のときと同じく、改行不可です。  その後の } までは1行で書いてもいいし、改行してもいいようです。  また、ループを囲む書式として |(パイプライン)で囲む書式と do ~ end で囲む書式と両方とも文法として成り立つようですし、同じ結果になります。  これを実行すると以下のような結果となります。
[6] key = foo  value = bar
[6] key = hoge  value = fuga
[10] key = foo
[10] key = hoge
[14] value = bar
[14] value = fuga
[20] key = foo  value = bar
[20] key = hoge  value = fuga
[24] key = foo
[24] key = hoge
[28] value = bar
[28] value = fuga
 同じ結果を得られる each_pair というのがあるようですが、処理が全く同じなら each だけ知ってればいいかな。  each_pair は each_key や each_value との対比であるのでしょうね。

5. キーを持っているか has_key?

 has_key? も include? も key?(key) も member?(key) も全部同じ。

has_key?(key)
include?(key)
key?(key)
member?(key)
 どれも同じ形式で bool 値を返してきます。
#!/usr/bin/env ruby

hash = { :foo => 'fufufu' }

puts('hash.has_key?(:foo) = ['"#{hash.has_key?(:foo)}"']')
puts('hash.has_key?(:bar) = ['"#{hash.has_key?(:bar)}"']')

puts('hash.include?(:foo) = ['"#{hash.include?(:foo)}"']')
puts('hash.include?(:bar) = ['"#{hash.include?(:bar)}"']')

puts('hash.key?(:foo) = ['"#{hash.key?(:foo)}"']')
puts('hash.key?(:bar) = ['"#{hash.key?(:bar)}"']')

puts('hash.member?(:foo) = ['"#{hash.member?(:foo)}"']')
puts('hash.member?(:bar) = ['"#{hash.member?(:bar)}"']')

 上記のコードを実行すると、下記の結果になります、

> ./ソースファイル名.rb
hash.has_key?(:foo) = [true]
hash.has_key?(:bar) = [false]
hash.include?(:foo) = [true]
hash.include?(:bar) = [false]
hash.key?(:foo) = [true]
hash.key?(:bar) = [false]
hash.member?(:foo) = [true]
hash.member?(:bar) = [false]

6. 削除

 ハッシュ変数.delete(キー) でキーを削除することができます。
hash1 = { :foo => 'bar', :hoge => 'fuga', :baz => 'qux' }
hash2 = { :foo => 'bar', :hoge => 'fuga', :baz => 'qux' }

puts "[#{__LINE__}] hash1 = #{hash1}"
puts "[#{__LINE__}] hash2 = #{hash2}"

hash1.delete(:hoge)

puts "[#{__LINE__}] hash1 = #{hash1}"

hash2.each do | key, value |
  if (key[0] == 'h')
    hash2.delete(key)
  end
end

puts "[#{__LINE__}] hash2 = #{hash2}"

 上記のソースを書いて実行すると下記の結果が得られます。
[4] hash1 = {:foo=>"bar", :hoge=>"fuga", :baz=>"qux"}
[5] hash2 = {:foo=>"bar", :hoge=>"fuga", :baz=>"qux"}
[9] hash1 = {:foo=>"bar", :baz=>"qux"}
[17] hash2 = {:foo=>"bar", :baz=>"qux"}
 hash2 の例の場合、ループ内でキーを削除するので例外となるかも?と思ったのですが、正常に動作するようです。