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.

Respostas:


201

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


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]

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? }

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.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.