Ruby Array find_first Objekt?


135

Vermisse ich etwas in der Array-Dokumentation? Ich habe ein Array, das bis zu einem Objekt enthält, das ein bestimmtes Kriterium erfüllt. Ich möchte dieses Objekt effizient finden. Die beste Idee, die ich aus den Dokumenten habe, ist folgende:

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

Aber ich bin aus zwei Gründen unzufrieden:

  1. Das selecthat mich dazu gebracht, das ganze Array zu durchqueren, obwohl wir nach dem ersten Treffer hätten aussteigen können.
  2. Ich brauchte eine Codezeile (mit einer Bedingung), um die Kandidaten zu reduzieren.

Beide Operationen sind verschwenderisch mit dem Vorwissen, dass es 0 oder 1 zufriedenstellende Objekte gibt.

Was ich möchte, ist so etwas wie:

array.find_first(block)

Dies gibt nil oder das erste Objekt zurück, für das der Block true ergibt, und beendet die Durchquerung an diesem Objekt.

Muss ich das selbst schreiben? All diese anderen großartigen Methoden in Array lassen mich denken, dass es da ist und ich sehe es einfach nicht.

Antworten:


201

Entweder verstehe ich Ihre Frage nicht, oder Enumerable # find ist das , wonach Sie gesucht haben.


32
Kein Problem, ich finde es auch oft ärgerlich, dass in der Ruby-Dokumentation nicht alle geerbten oder enthaltenen Klassen und Module aufgelistet sind.
Mladen Jablanović

4
Weitere Informationen: Die [1,2,3,5,2].find { |n| puts n; n == 2 } Iteration wird beendet, sobald das erste übereinstimmende Element gefunden wurde.
RajuGT

97

Verwenden Sie die Array- detectMethode, wenn Sie den ersten Wert zurückgeben möchten, wobei block true zurückgibt

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

OR

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

Wenn Sie alle Werte zurückgeben möchten, bei denen block true zurückgibt, verwenden Sie select

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

5
.detectist genau das, was ich brauche. Aber was ist dann der Unterschied .find?
Augustin Riedinger

13
@ AugustinRiedinger kein Unterschied, beide sind gleich. detectist nur ein Alias ​​für find ruby-doc.org/core-2.1.2/Enumerable.html#method-i-find
Sandip Ransing

Aus Gründen der Konsistenz folge ich gerne dem Ruby Style Guide , der den Fund bevorzugt
Paul van Leeuwen

20

Vermutlich haben Sie gerade die Suchmethode in den Dokumenten verpasst:

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

8
Oder wenn Sie Code-Golf mögen,my_array.find(&:satisfies_condition?)
Andrew Grimm

14

Müssen Sie das Objekt selbst oder brauchen Sie nur zu wissen , ob es ist ein Objekt , das genügt. Wenn erstere dann ja: benutze find:

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

sonst kannst du verwenden any?

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

Letzterer wird mit "wahr" auf Kaution gehen, wenn er eine findet, die die Bedingung erfüllt. Ersteres wird dasselbe tun, aber das Objekt zurückgeben.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.