Hashクラス(以下「Hash」と略記)は、Arrayに次いでよく使われるコンテナーです。「連想配列」や「ハッシュテーブル」と呼ぶこともあります。
Arrayでは要素の位置を示す整数インデックスとオブジェクトのペアでオブジェクトを管理していました。Hashでは、要素の位置を表す整数インデックスの代わりに、シンボルや文字列など、任意のオブジェクトをキーにして、オブジェクトを指し示すことができます。
では、Hashの基本操作を覚えるために、pryを使って以下のように実行してみましょう。
[1] pry(main)> hash = {"jack" => 11, "queen" => 12, :king => 13} => {"jack"=>11, "queen"=>12, :king=>13}
まず、[1]では連想配列のオブジェクトを作成し、変数「hash」に代入しています。「{key1 => value1, key2 => value2, …… }」という形で連想配列を初期化できます。
また、Hash#lengthまたはHash#sizeを使うことで、連想配列に含まれている要素数を取得できます。
[2] pry(main)> hash.length => 3 [3] pry(main)> hash.size => 3
連想配列の要素にアクセスする場合は[](角カッコ)を使います。[6]のように、存在しないキーを指定するとnilが返ります。
[4] pry(main)> hash["queen"] => 12 [5] pry(main)> hash[:king] => 13 [6] pry(main)> hash[:ace] => nil
キーの一覧やキーに関連付けられたオブジェクトの一覧は、Hash#keysとHash#valuesで得ることができます。[7]のように、Hash#keysはキーの一覧を配列として返します。また、[8]のように、Hash#valuesはオブジェクトの一覧を配列として返します。
[7] pry(main)> hash.keys => ["jack", "queen", :king] [8] pry(main)> hash.values => [11, 12, 13]
連想配列にオブジェクトを格納するときは、[](角カッコ)と「=」演算子を使います。[9]で「:ace」をキーとして「1」という整数を格納しており、[10]のようにhashの内容を確認すると、「:ace=>1」が格納されていることが分かります。[11]では[](角カッコ)を使って、「:ace」をキーとするオブジェクトを取り出しています。
[9] pry(main)> hash[:ace] = 1 => 1 [10] pry(main)> hash => {"jack"=>11, "queen"=>12, :king=>13, :ace=>1} [11] pry(main)> hash[:ace] => 1
また、Hash#deleteを使うと、引数に指定したオブジェクトをキーとする要素を、連想配列から取り除けます。
[12]では"jack"という文字列をキーとする要素を取り除いており、[13]のようにhashの内容を確認すると、「"jack"=>11」という要素が取り除かれていることが分かります。
[12] pry(main)> hash.delete("jack") => 11 [13] pry(main)> hash => {"queen"=>12, :king=>13, :ace=>1}
最後に、Hash#clearは連想配列を空にするためのメソッドです。[14]でHash#clearを用いてhashを空にし、[15]でhashが空になったことを確認しています。
[14] pry(main)> hash.clear => {} [15] pry(main)> hash => {}
空の連想配列を作る場合には、2通りの方法があります。「{}」リテラルを用いる場合と、Hashのクラスメソッド「new」を用いてオブジェクトを生成する場合です。
[1] pry(main)> hash = {} => {} [2] pry(main)> hash = Hash.new => {}
連想配列を初期化する場合、基本的に「{key1 => value1, key2 => value2, …… }」という形式で書きます。シンボルを使う場合も、この記法が使えます。
[1] pry(main)> {:jack => 11, :queen => 12, :king => 13} => {:jack=>11, :queen=>12, :king=>13}
ただし、Rubyではシンボルをキーとした連想配列がよく使われるので、シンボルをキーとする連想配列用の「シンタックスシュガー」(糖衣構文、プログラミング言語において、読み書きのしやすさのために導入される構文)があります。
「{key1: value1, key2: value2, …… }」というように、キーの後に「: 」が来てその後に値を指定する形式で書けます。
[2] pry(main)> {jack: 11, queen: 12, king: 13} => {:jack=>11, :queen=>12, :king=>13}
[2]は[1]と等価ですが、[2]の方がよりスッキリとしていて見やすいため、多くのRubyプログラマーはこのシンタックスシュガーを好みます。
通常、存在しないキーを指定してオブジェクトを取り出そうとすると、nilが返ります。しかし、場合によっては、キーが存在しない場合に別のオブジェクトを返したいことがあります。そのようなときは、連想配列の初期化の際にデフォルト値を指定できます。
[1] pry(main)> hash = Hash.new(:default) => {} [2] pry(main)> hash[:ace] => :default
ここでは、[1]のようにHash.newの引数にデフォルト値として「:default」というシンボルを設定しています。そのため、[2]のように存在しないキー「:ace」を使ってオブジェクトを取り出すと、シンボル「:default」が返ります。
Hash#to_aを使うと、連想配列から配列を生成できます。この場合、キーと値で構成されている要素数2の配列が複数並んだ配列(配列の配列)が返ります。少しややこしいですが、[1]の例を見れば理解できると思います。
[1] pry(main)> {jack: 11, queen: 12, king: 13}.to_a => [[:jack, 11], [:queen, 12], [:king, 13]]
Hash#flattenを使うと、連想配列を平滑化したような配列を生成できます。Hash#to_aとは違い、キーと値が順に並んだような配列が生成されます。
[1] pry(main)> {jack: 11, queen: 12, king: 13}.flatten => [:jack, 11, :queen, 12, :king, 13]
連想配列を統合するときには、Hash#mergeを使います。Hash#mergeは、自身と引数に与えたハッシュを統合したハッシュを返します。Hash#merge!はHash#mergeの破壊的メソッド版です。
[1] pry(main)> {jack: 11, queen: 12, joker: 14}.merge({ace: 1, king: 13, joker: 15}) => {:jack=>11, :queen=>12, :joker=>15, :ace=>1, :king=>13}
この例のようにキーが重複した場合(:joker)は、Hash#mergeの引数に与えたキーとオブジェクトのペアが優先されます。
キーと値の関係を逆転させたような連想配列を生成するときは、Hash#invertが便利です。ただし、入れ替え後にキーが重複してしまう場合の動作は不定です。
[1] pry(main)> {jack: 11, queen: 12, king: 13}.invert => {11=>:jack, 12=>:queen, 13=>:king}
Arrayと同様、Hashについても使用頻度の高いメソッドを幾つか紹介しました。もっとHashについて知りたい場合は、リファレンスマニュアルを見てください。
次回は、引き続きRubyの組み込みライブラリから紹介しますので、お楽しみに。
麻田 優真(Rails技術者認定シルバー試験問題作成者)
イタリア、ローマ生まれ。中学生のころHSPに初めて触れ、プログラミングの楽しさを知る。オープンソースやハッカーカルチャーを好む。C#からRubyに転向したときに、動的型付け言語の柔軟性やメタプログラミングの魅力に感動し、Rubyとともにプログラマーとしての人生を歩む決意を固める。
現在は奈良先端科学技術大学院大学で学生として所属するかたわら、株式会社アジャイルウェアでプログラマーとして従事。Ruby on Railsによるコンシューマー向けのWebサービスの開発などに尽力している。
好きなメソッドは、define_method。
Twitter:@Mozamimy、ブログ:http://blog.quellencode.org/
山根 剛司(Ruby業務開発歴7年)
兵庫県生まれ。1997年からベンチャー系のパッケージベンダーで10年間勤務。当時、使用していた言語はJavaとサーバーサイドJavaScript。
2007年よりITコンサル会社に転職し、Rubyと出会って衝撃を受ける。基幹システムをRuby on Railsで置き換えるプロジェクトに従事。それ以来Ruby一筋で、Ruby on Railsのプラグインやgemも開発。
2013年より、株式会社アジャイルウェアに所属。アジャイルな手法で、Ruby on Railsを使って企業向けシステムを構築する業務に従事。
Ruby関西所属。
Twitter:@spring_kuma、Facebook:山根 剛司
Copyright © ITmedia, Inc. All Rights Reserved.