Rubyでは、条件に一致した要素を取得したい場合に「find」メソッドが利用できます。
本記事では、findメソッドの基本的な使い方と混乱してしまいがちな「detect」メソッド・「select」メソッドとの違いについてご紹介していきたいと思います。
目次
findメソッドとは
findメソッドは、「Enumerable」というRubyの標準モジュールより提供されている、配列やハッシュから指定した条件に一致する「最初の要素」を返却する機能です。
基本構文
findメソッドの基本的な書き方をまずは確認しておきます。
オブジェクト.find{ |要素| 条件式 }
オブジェクトに格納された値を要素として1つずつ評価していき、条件式と一致する最初の要素が返却されます。
具体例をサンプルで確認していきましょう。
配列の要素を検索するサンプル
配列をオブジェクトとして指定し、3で割り切れる最初の要素を出力するサンプルです。
arrayObj = [1, 2, 3, 4, 5, 6] puts arrayObj.find{ |n| n % 3 == 0 }
実行結果
$ruby sample.rb 3
サンプルでは配列に指定した値が「1」から順番に「n」に代入された形の条件式で評価され、最初に式が「true」となる「3」が結果として出力されます。
ハッシュの要素を検索するサンプル
オブジェクトにハッシュを指定して、条件式に該当する要素を抽出してみましょう。
employee = {"田中" => 30, "鈴木" => 25, "山本" => 35, "佐藤" => 40, "藤原" => 28} p employee.find{ |k, v| v > 30 }
実行結果
$ruby sample.rb ["山本", 35]
サンプルの場合、[“田中”, 30]から順番にv(value)の値を条件式で評価していき、最初に式が成立する[“山本”, 35]が出力されています。
もちろんkeyの値を条件式として指定することも可能です
employee = {"田中" => 30, "鈴木" => 25, "山本" => 35, "佐藤" => 40, "藤原" => 28} p employee.find{ |k, v| k == "田中" }
実行結果
$ruby sample.rb ["田中", 30]
要素にはk(key)とv(value)を指定しており、条件式には任意の要素だけを利用することも可能です。
オブジェクトに条件式と一致する要素が存在しない場合のサンプル
オブジェクトに条件式と一致する要素が存在しない場合の取得結果も確認しておきましょう。
サンプルでは「1~6」までを格納した配列に対して、「7」で割り切れるという条件を指定しているため、要素が取得出来ないサンプルです。
arrayObj = [1, 2, 3, 4, 5, 6] puts arrayObj.find{ |n| n % 7 == 0 }
実行結果
$ruby sample.rb
このように対象オブジェクトに該当要素が存在しない場合には、結果として何もコンソールには出力されず「nil」が返却されています。
findメソッドとdetectメソッドは違う?
findメソッドとdetectメソッドに機能としての違いはありません。
findメソッドの別名としてdetectメソッドが定義されています。
Ruby on Railsの「ActiveRecord」でもfindメソッドが存在し、Rubyの標準モジュールである「Enumerable」のfindメソッドと区別するために利用されることが多いようです。
detectメソッドの処理を確認しておく
findメソッドで掲載したサンプルをdetectメソッドに置き換えて、同じ処理結果が得られるのか確認しておきましょう。
配列のサンプル
配列オブジェクトに対してdetectメソッドを実行します。
arrayObj = [1, 2, 3, 4, 5, 6] puts arrayObj.detect{ |n| n % 3 == 0 }
実行結果
$ruby sample.rb 3
findメソッドで取得出来た結果と同じことが確認出来ます。
ハッシュのサンプル
ハッシュオブジェクトに対しても同様に、detectメソッドを実行します。
employee = {"田中" => 30, "鈴木" => 25, "山本" => 35, "佐藤" => 40, "藤原" => 28} p employee.find{ |k, v| v > 30 }
実行結果
$ruby sample.rb ["山本", 35]
ハッシュの場合もfindメソッド実行時と同じ結果が得られています。
findメソッドとselectメソッドの違い
findメソッドとselectメソッドには、処理内容に違いがあります。
findメソッドが条件に該当した最初の要素を取得するのに対し、selectメソッドでは条件に該当する全ての要素を取得します。
基本構文
selectメソッドの書き方はfindメソッドと同じで、下記のように記述します。
オブジェクト.select{ |要素| 条件式 }
オブジェクトに指定した配列またはマップから条件式に一致する要素全てを取得します。
配列の該当する要素を全て取得するサンプル
findメソッドのサンプルコードを、今度はselectメソッドに書き換えて実行してみましょう。
arrayObj = [1, 2, 3, 4, 5, 6] p arrayObj.select{ |n| n % 3 == 0 }
実行結果
$ruby sample.rb [3, 6]
findメソッドでは、最初の要素である「3」のみを取得していましたが、selectメソッドでは同じく割り切れる「6」も取得出来ています。
マップの該当する要素を全て取得するサンプル
同じくマップオブジェクトのサンプルをselectメソッドで書き換えて実行してみます。
employee = {"田中" => 30, "鈴木" => 25, "山本" => 35, "佐藤" => 40, "藤原" => 28} p employee.select{ |k, v| v > 30 }
実行結果
$ruby sample.rb {"山本"=>35, "佐藤"=>40}
fine_allとselectメソッドが同じ機能
findとselectメソッドでは取得結果が変わることをご紹介してきましたが、find_allメソッドとselectメソッドでは同じ結果が取得出来ます。
配列のオブジェクトをfind_allメソッドに書き換えて実行してみましょう。
arrayObj = [1, 2, 3, 4, 5, 6] p arrayObj.find_all{ |n| n % 3 == 0 }
実行結果
$ruby sample.rb [3, 6]
find_allメソッドであれば、selectメソッドと同じ結果を取得出来ることが確認出来ました。
さいごに: findメソッドを利用してRubyのオブジェクトから要素を取得してみよう
本記事では、Rubyプログラムにおけるfindメソッドを利用した要素の取得方法についてご紹介していきました。
オブジェクトから条件に一致する最初の要素を取得したい場合には「find」メソッドまたは「detect」メソッド、条件に一致する全ての要素を取得したい場合には「find_all」メソッドまたは「select」メソッドを利用してください。
オブジェクトから要素の取得は、実務でも頻繁に利用される処理ですので、しっかりとメソッドの使い方を理解しておきましょう。