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.

Respuestas:


201

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


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]

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

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.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.