O objeto Ruby Array find_first?

135

Estou faltando alguma coisa na documentação da matriz? Eu tenho uma matriz que contém até um objeto que satisfaz um determinado critério. Eu gostaria de encontrar com eficiência esse objeto. A melhor ideia que tenho dos documentos é a seguinte:

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

Mas estou insatisfeito por duas razões:

  1. Isso selectme fez atravessar todo o conjunto, mesmo que pudéssemos ter escapado depois do primeiro golpe.
  2. Eu precisava de uma linha de código (com uma condição) para achatar os candidatos.

Ambas as operações são um desperdício com o conhecimento prévio de que existem 0 ou 1 objetos satisfatórios.

O que eu gostaria é algo como:

array.find_first(block)

que retorna nulo ou o primeiro objeto para o qual o bloco é avaliado como verdadeiro, encerrando a travessia nesse objeto.

Devo escrever isso sozinho? Todos esses outros ótimos métodos em Array me fazem pensar que está lá e eu simplesmente não estou vendo.

o homem de lata
fonte

Respostas:

201

Ou eu não entendo sua pergunta ou #Enumerable # find é o que você estava procurando.

Mladen Jablanović
fonte
32
Sem problemas, também acho irritante que a documentação do ruby ​​não liste métodos de todas as classes e módulos herdados ou incluídos.
Mladen Jablanović
4
mais informações: a [1,2,3,5,2].find { |n| puts n; n == 2 } iteração para quando encontra o primeiro elemento correspondente.
rajuGT
97

use o detectmétodo array se você deseja retornar o primeiro valor em que block retorna true

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

OR

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

Se você deseja retornar todos os valores em que block retorna true, use select

[1,2,3,11,34].select(&:even?)  #=> [2, 34]
Sandip Ransing
fonte
5
.detecté exatamente o que eu preciso. Mas qual é a diferença .findentão?
Augustin Riedinger
13
@AugustinRiedinger nenhuma diferença, ambos são iguais. detecté apenas um alias para find ruby-doc.org/core-2.1.2/Enumerable.html#method-i-find
Sandip Ransing
para alguma consistência, eu gosto de seguir o Guia de Estilo Ruby , que é o favor de encontrar
Paul van Leeuwen
20

Acho que você acabou de perder o método find nos documentos:

my_array.find {|e| e.satisfies_condition? }
sepp2k
fonte
8
Ou se você gosta de golfe código,my_array.find(&:satisfies_condition?)
Andrew Grimm
14

Você precisa do objeto em si ou você apenas precisa de saber se existe é um objeto que satisfaz. Se o primeiro for sim: use find:

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

caso contrário, você pode usar any?

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

O último será liberado com "true" quando encontrar um que satisfaça a condição. O primeiro fará o mesmo, mas retornará o objeto.

Taryn East
fonte