こんにちは!Webコーダー・プログラマーの貝原(@touhicomu)です。
今日は、Rubyのハッシュ(hash)のfindメソッドについて書きたいと思います。
Rubyをプログラミングしていると、「hashをkeyや値で検索したい!」という時ってありますよね。
そういった時にhashのfindメソッドを使用します。
今回はそんなfindメソッドについて、
【基礎】ハッシュのキーで検索する
【基礎】ハッシュの値で検索する
【発展】ハッシュのfind_allメソッドで検索する
【発展】ハッシュを、正規表現(regex)検索する
について、解説したいと思います。
findメソッドの使い方を網羅的に解説していますので、ぜひ参考にしてくださいね!
ハッシュのfindメソッドで検索する
ハッシュのfindメソッドとは
hashのfindメソッドは、指定した要素を検索して取得することができるブロックつきのメソッドです。
ブロックを渡すと、ブロック変数にhashの要素のkeyと値が渡されます。
そして、keyまたは値が条件に該当するkeyや値である場合は、ブロックの戻値をtrueとして返すようブロックのロジックを組みます。
そうすることで、findメソッドは、ブロックの戻値がtrueとなった要素を返します。
これが、findメソッド、及び、それに渡すブロックの仕組みの概要です。
これだけでは、わかりづらいと思いますので、次章以降で、詳しく解説しています。
なお、ブロックについての理解を前提としていますので、ブロックについての知識があやふやな方はまずこちらの記事を参考にしてみてください。
ハッシュのキーで検索する
まずは、hashのkeyで検索してみましょう。
ここでは、keyが30である要素を検索してみます。
サンプルコード:
h = { 10 => "abc", 20 => "def", 30 => "ghi" } p h.find {|k,v| k == 30}
サンプルコードの実行結果:
[30, "ghi"]
以上のように、key==30の条件にマッチするhashの要素を検索できていますね。
findメソッドにブロックを引数と渡して、ブロック変数としてkeyと値を取得します。
ブロック変数のうち、keyに条件をつけます。
そのkeyに対する条件式をブロックの戻値にします。
戻値にした条件式がtrueの場合に、findメソッドが要素を検索結果として返します。
ハッシュの値で検索する
次に、hashの値で検索してみましょう。
先ほどと同様に、findメソッドにブロックを引数と渡して、ブロック変数としてkeyと値を取得します。
ここでは、値が”def”である要素を検索してみます。
サンプルコード:
h = { 10 => "abc", 20 => "def", 30 => "ghi" ,40 =>"def"} p h.find {|k,v| v == "def" }
サンプルコードの実行結果:
[20, "def"]
初めの要素である20, “def”は取得できてますが、40 => “def”は取得できていません。
それはfindメソッドでは条件にマッチする一番最初の要素しか検索できないからです。
ハッシュのfind_allメソッドで検索する
hashのfindメソッドでは、条件にマッチする一番最初の要素しか検索できませんでした。
しかし、hashのfnd_allメソッドを使用すれば、条件にマッチする全ての要素を配列として取得できます。
ここでは、keyが3以上のhashの要素をすべて配列として取得してみます。
サンプルコード:
h = { 1 => "B001", 2 => "A123", 3 => "D001", 4 => "E900", 5 => "G555" } ret = h.find_all {|k,v| k >= 3 } p ret p ret.to_h
サンプルコードの実行結果:
[[3, "D001"], [4, "E900"], [5, "G555"]] {3=>"D001", 4=>"E900", 5=>"G555"}
以上のように、hashからfind_allメソッドにより、値が3以上との条件にマッチするすべての要素を配列として取得できていますね。
また、to_hメソッドにより、findメソッドの戻値を、ハッシュにすることもできています。
to_hメソッドは、ruby ver2.1以上で使用可能です。
ハッシュを、正規表現(regex)検索する
findメソッドを応用すると、正規表現(regex)による検索も可能となります。
正規表現の詳細の解説は致しませんが、簡単に述べますと、正規表現による検索とはパターンにより文字列のマッチングを行うことです。
こちらの記事で詳しく説明されていますので正規表現についてわからない方はこちらを参考にしてみてください。
正規表現のパターンの例として、/A\d+/を挙げます。
Rubyの正規表現ではまず//を使って正規表現を囲む必要があります。
そしてAは大文字のAそのもので、\dは[0-9]と同じ意味でいずれかの数字、+は1回以上繰り返すです。
なので、この正規表現では極端な例でいうと、「A894179356196370874」、「A2」、「A999999999999999999999」などがマッチします。
ここで正規表現/A\d+/を文字列のmatchメソッドの引数に渡して実行すると、文字列がパターンにマッチした場合はtrueと等価になります。
実際に例を挙げて解説します。
ここでは、findメソッドの引数に渡したブロックで、ブロック変数としてkeyと値を受け取り、値に対し、to_sメソッドを適用して文字列に変換してから、matchメソッドを使用します。
ブロックの戻値には、matchメソッドの戻値を使用します。
そうすることで、マッチした際にブロックの戻値がtrueとなり、findメソッドがマッチしたhashの要素を返します。
サンプルコード:
h = { 10 => "SUB-B001", 20 => "SUB-A123", 30 => "SUB-D001" } p h.find {|k,v| v.to_s.match(/A\d+/) }
サンプルコードの実行結果:
[20, "SUB-A123"]
以上のように、hashの中から、正規表現/A\d+/にマッチする値をもつ要素を検索できていますね。
(A123がマッチしました)
まとめ
いかがでしたでしょうか。
ここでは、Rubyのhashのkeyや値を検索するfindメソッドについて解説しました。
hashを検索することはRubyをプログラミングする上で、頻出するコードですので、この機会に、ぜひ、覚えられてください。
また、find_allメソッドというメソッドも紹介しました。findメソッドと違い、条件にマッチするhashの要素すべてを、配列として取得できます。
これは大変重宝しますので、動作をよく把握されておいてください。
また、findメソッドの応用として、正規表現検索もできることも紹介しました。
正規表現による検索はRubyの中でも非常に重要で強力な検索の方法です。しっかりと把握されておいてください。
hashの要素の検索の使い方を忘れたら、またこの記事を読み返してみてください。