Ruby配列find_firstオブジェクト?


135

Arrayドキュメントに何か不足していますか?特定の条件を満たすオブジェクトを1つまで含む配列があります。そのオブジェクトを効率的に見つけたいのですが。ドキュメントから私が持っている最高のアイデアはこれです:

candidates = my_array.select { |e| e.satisfies_condition? }
found_it = candidates.first if !candidates.empty?

しかし、私は2つの理由で満足していません。

  1. select最初のヒットの後で保釈できたとしても、それでアレイ全体をトラバースできました。
  2. 候補を平坦化するために、(条件付きの)コード行が必要でした。

どちらの操作も、満足のいくオブジェクトが0または1あることを事前に認識しているため、無駄が多くなります。

私が欲しいのは次のようなものです:

array.find_first(block)

これは、nil、またはブロックがtrueと評価された最初のオブジェクトを返し、そのオブジェクトでの走査を終了します。

これを自分で書かなければなりませんか?Arrayの他のすばらしいメソッドはすべて、私はそれがそこにあると考えさせ、私はそれを目にしていません。

回答:


201

私はあなたの質問を理解していないか、Enumerable#findがあなたが探していたものです。


32
問題ありません。Rubyのドキュメントに、継承または含まれているすべてのクラスとモジュールのメソッドがリストされていないこともよくあります。
MladenJablanović10年

4
詳細:[1,2,3,5,2].find { |n| puts n; n == 2 } 一致する最初の要素が見つかると、反復は停止します。
rajuGT 2017

97

detectブロックがtrueを返す最初の値を返したい場合は、配列メソッドを使用します

[1,2,3,11,34].detect(&:even?) #=> 2

OR

[1,2,3,11,34].detect{|i| i.even?} #=> 2

blockがtrueを返すすべての値を返したい場合は、 select

[1,2,3,11,34].select(&:even?)  #=> [2, 34]

5
.detectまさに私が必要とするものです。しかし、そのときの違いは何.findですか?
オーガスティンリーディンガー2014

13
@AugustinRiedinger違いはありません、両方とも同じです。ruby-doc.org/core-2.1.2/Enumerable.html#method-i-findのdetectエイリアスにfind すぎません
Sandip Ransing

いくつかの一貫性を保つために私は従うのが好きRubyのスタイルガイドの恩恵が見つけ、
ポールバンレイバン

20

あなたはドキュメントのfindメソッドを逃したと思います:

my_array.find {|e| e.satisfies_condition? }

8
または、コードゴルフが好きな場合my_array.find(&:satisfies_condition?)
Andrew Grimm

14

オブジェクト自体が必要ですか、それとも、満足するオブジェクトあるかどうかを知る必要があるだけですか。前者の場合、はい:findを使用します:

found_object = my_array.find { |e| e.satisfies_condition? }

それ以外の場合は使用できます any?

found_it = my_array.any?  { |e| e.satisfies_condition? }

後者は、条件を満たすものを見つけると「true」で保釈されます。前者は同じことをしますが、オブジェクトを返します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.