Ruby Array find_first object?

135

¿Me falta algo en la documentación de la matriz? Tengo una matriz que contiene hasta un objeto que cumple un cierto criterio. Me gustaría encontrar eficientemente ese objeto. La mejor idea que tengo de los documentos es esta:

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

Pero no estoy satisfecho por dos razones:

  1. Eso selectme hizo atravesar todo el conjunto, a pesar de que podríamos habernos rescatado después del primer golpe.
  2. Necesitaba una línea de código (con una condición) para aplanar a los candidatos.

Ambas operaciones son un desperdicio con el conocimiento previo de que hay 0 o 1 objetos satisfactorios.

Lo que me gustaría es algo como:

array.find_first(block)

que devuelve nil o el primer objeto para el cual el bloque se evalúa como verdadero, finalizando el recorrido en ese objeto.

¿Debo escribir esto yo mismo? Todos esos otros excelentes métodos en Array me hacen pensar que está allí y simplemente no lo veo.

el hombre de hojalata
fuente

Respuestas:

201

O no entiendo tu pregunta, o Enumerable # find es lo que estabas buscando.

Mladen Jablanović
fuente
32
No hay problema, también a menudo me molesta que la documentación de Ruby no enumere los métodos de todas las clases y módulos heredados o incluidos.
Mladen Jablanović
44
Más información: la [1,2,3,5,2].find { |n| puts n; n == 2 } iteración se detiene una vez que encuentra el primer elemento que coincide.
rajuGT
97

use el detectmétodo de matriz si desea devolver el primer valor donde el bloque devuelve verdadero

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

OR

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

Si desea devolver todos los valores donde el bloque devuelve verdadero, use select

[1,2,3,11,34].select(&:even?)  #=> [2, 34]
Sandip Ransing
fuente
55
.detectes exactamente lo que necesito Pero, ¿cuál es la diferencia con .findentonces?
Augustin Riedinger
13
@AugustinRiedinger no hay diferencia, ambos son iguales. detectes solo un alias para find ruby-doc.org/core-2.1.2/Enumerable.html#method-i-find
Sandip Ransing
para un poco de coherencia, me gusta seguir The Ruby Style Guide , que favorece encontrar
Paul van Leeuwen
20

Supongo que te perdiste el método de búsqueda en los documentos:

my_array.find {|e| e.satisfies_condition? }
sepp2k
fuente
8
O si te gusta el golf de código,my_array.find(&:satisfies_condition?)
Andrew Grimm
14

¿Necesita el objeto mismo o sólo necesita saber si hay es un objeto que satisface. Si es lo primero, entonces sí: use find:

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

de lo contrario puedes usar any?

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

Este último saldrá con "verdadero" cuando encuentre uno que satisfaga la condición. El primero hará lo mismo, pero devolverá el objeto.

Taryn East
fuente