Об'єкт Ruby Array find_first?


135

Я щось пропускаю в документації на масив? У мене є масив, який містить до одного об'єкта, що відповідає певному критерію. Я хотів би ефективно знайти цей об’єкт. Найкраща ідея, яку я маю в документах, така:

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

Але я незадоволений з двох причин:

  1. Це selectзмусило мене об'їхати весь масив, хоча ми могли врятувати після першого влучення.
  2. Мені знадобився рядок коду (з умовою), щоб вирівняти кандидатів.

Обидві операції марні, маючи передбачення, що 0 або 1 задовольняючих об'єктів.

Мені б хотілося щось таке:

array.find_first(block)

який повертає нуль або перший об'єкт, для якого блок оцінює істинне, закінчуючи обхід цього об'єкта.

Повинен я сам це написати? Усі ці чудові методи в Array змушують мене думати, що він є, і я просто не бачу цього.

Відповіді:


201

Або я не розумію вашого запитання, або численні знахідки - це те, що ви шукали.


32
Без проблем, мені також часто прикро, що рубінова документація не перелічує методів усіх успадкованих або включених класів і модулів.
Младен Ябланович

4
детальніше: [1,2,3,5,2].find { |n| puts n; n == 2 } ітерація припиняється, як тільки знайде перший елемент, який відповідає.
rajuGT

97

використовуйте detectметод масиву, якщо ви хочете повернути перше значення там, де блок повертає істину

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

OR

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

Якщо ви хочете повернути всі значення, де блок повертає істину, тоді використовуйте select

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

5
.detectсаме те, що мені потрібно. Але яка тоді різниця .find?
Августин Рідінгер

13
@AugustinRiedinger різниці немає, обидва однакові. detectє лише псевдонімом find ruby-doc.org/core-2.1.2/Enumerable.html#method-i-find
Сандіп Рансінг

для деякої послідовності мені подобається дотримуватися керівництва по стилю Ruby , який сприяє пошуку
Пол ван

20

Здогадайтесь, ви просто пропустили метод пошуку в документах:

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

8
Або якщо вам подобається кодовий гольф,my_array.find(&:satisfies_condition?)
Ендрю Грімм

14

Вам потрібен сам об’єкт або вам просто потрібно знати, чи є об'єкт, який задовольняє. Якщо перший, то так: використовуйте find:

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

інакше можна використовувати any?

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

Останній буде порушити "справжній", коли знайде той, який задовольняє умові. Перший зробить те саме, але поверне об’єкт.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.