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)

который возвращает nil или первый объект, для которого блок оценивается как true, заканчивая обход этого объекта.

Должен ли я написать это сам? Все эти другие замечательные методы в Array заставляют меня думать, что это там, и я просто не вижу этого.

Ответы:


201

Либо я не понимаю ваш вопрос, либо Enumerable # find - это то, что вы искали.


32
Нет проблем, я также часто нахожу раздражающим, что документация ruby ​​не перечисляет методы всех унаследованных или включенных классов и модулей.
Младен Ябланович

4
больше информации: [1,2,3,5,2].find { |n| puts n; n == 2 } итерация останавливается, когда он находит первый элемент, которому соответствует.
rajuGT

97

используйте detectметод массива, если вы хотите вернуть первое значение, где блок возвращает true

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

OR

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

Если вы хотите вернуть все значения, где блок возвращает true, используйте 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
Sandip Ransing

для некоторой последовательности я хотел бы следовать Руководству по стилю 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? }

Последний выдает «true», когда находит тот, который удовлетворяет условию. Первый сделает то же самое, но вернет объект.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.