Objet find_first Ruby Array?

135

Est-ce que je manque quelque chose dans la documentation Array? J'ai un tableau qui contient jusqu'à un objet satisfaisant à un certain critère. J'aimerais trouver efficacement cet objet. La meilleure idée que j'ai de la documentation est la suivante:

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

Mais je ne suis pas satisfait pour deux raisons:

  1. Cela selectm'a fait parcourir tout le tableau, même si nous aurions pu renflouer après le premier coup.
  2. J'avais besoin d'une ligne de code (avec une condition) pour aplatir les candidats.

Les deux opérations sont inutiles avec la prescience qu'il y a 0 ou 1 objet satisfaisant.

Ce que je voudrais, c'est quelque chose comme:

array.find_first(block)

qui renvoie nil ou le premier objet pour lequel le bloc est évalué à vrai, mettant fin au parcours à cet objet.

Dois-je écrire cela moi-même? Toutes ces autres méthodes géniales dans Array me font penser que c'est là et je ne le vois tout simplement pas.

l'homme d'étain
la source

Réponses:

201

Soit je ne comprends pas votre question, soit Enumerable # find est ce que vous cherchiez.

Mladen Jablanović
la source
32
Pas de problème, je trouve aussi souvent ennuyeux que la documentation ruby ​​ne répertorie pas les méthodes de toutes les classes et modules hérités ou inclus.
Mladen Jablanović
4
plus d'infos: l' [1,2,3,5,2].find { |n| puts n; n == 2 } itération s'arrête une fois qu'il trouve le premier élément auquel il correspond.
rajuGT
97

utilisez la detectméthode de tableau si vous voulez retourner la première valeur où le bloc retourne vrai

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

OR

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

Si vous souhaitez renvoyer toutes les valeurs où block retourne true, utilisez select

[1,2,3,11,34].select(&:even?)  #=> [2, 34]
Sandip Ransing
la source
5
.detectest exactement ce dont j'ai besoin. Mais quelle est la différence avec .findalors?
Augustin Riedinger le
13
@AugustinRiedinger aucune différence, les deux sont identiques. detectest juste un alias de find ruby-doc.org/core-2.1.2/Enumerable.html#method-i-find
Sandip Ransing
pour un peu de cohérence, j'aime suivre The Ruby Style Guide , qui favorise la recherche
Paul van Leeuwen
20

Je suppose que vous venez de manquer la méthode de recherche dans la documentation:

my_array.find {|e| e.satisfies_condition? }
sepp2k
la source
8
Ou si vous aimez le golf codé,my_array.find(&:satisfies_condition?)
Andrew Grimm
14

Est - ce que vous avez besoin de l'objet lui - même ou avez - vous juste besoin de savoir s'il est un objet qui satisfait. Si le premier alors oui: utilisez find:

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

sinon vous pouvez utiliser any?

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

Ce dernier renoncera à "vrai" lorsqu'il en trouvera un qui satisfait à la condition. Le premier fera de même, mais retournera l'objet.

Taryn Est
la source