ruby enumerables: есть ли обнаружение результатов оценки блока?

Я ищу что-то похожее на #detect в перечислениях, но не совсем. Вот что делает перечисление:

[1, 2, 3].detect {|i| i > 1 } #=> 2

он возвращает первый экземпляр массива, который соответствует условию. Теперь моя цель - вернуть значение блока. Беспокойство вызывает не совсем условия, а, например, первое, которое не равно нулю. Что-то вроде этого:

[var1, var2, var3].wanted_detect {|var| another_function(var) } 

в котором функция вернет первый результат вызова other_function, который не равен нулю.

Сопоставление значений применения метода к переменным, а затем использование обнаружения не является вариантом. В идеале это должно работать в ленивых счетчиках, для которых раннее сопоставление всех возможных значений недопустимо.


person ChuckE    schedule 25.07.2013    source источник


Ответы (1)


[var1, var2, var3].lazy.map { |var| another_function(var) }.reject(&:nil?).first

Если у вас нет доступа к Enumerable#lazy, реализовать то, что вы хотите, достаточно просто:

module Enumerable
  def wanted_detect
    self.each do |obj|
      val = yield obj
      return val if val
    end
  end
end

Демо:

[1, 2, 3, 4].wanted_detect { |x| x*x if x > 2 }
# => 9

РЕДАКТИРОВАТЬ: Извините, я пропустил последний абзац, пока на него не указал falsetru.

Спасибо за комментарии, фальцет.

person Amadan    schedule 25.07.2013
comment
ОП сказал Mapping the values of applying the method on the variables and then using detect is not an option. - person falsetru; 25.07.2013
comment
В блоках вы не вызываете another_function. Должно быть another_function(var). - person falsetru; 25.07.2013
comment
нет, у меня нет доступа к lazy (1.9.3). поправьте меня, если я ошибаюсь, но компакт не возвращает массив? это означает, что, вызывая compact для перечислимого, я буду преобразовывать его в массив перед первым вызовом, тем самым без необходимости вызывая other_function для каждого элемента моего массива? - person ChuckE; 25.07.2013
comment
я хотел бы использовать комбинацию в существующем API и не писать свою собственную перечислимую реализацию, я хочу посмотреть, возможно ли это с существующим API. - person ChuckE; 25.07.2013
comment
Я получаю сообщение об ошибке undefined method compact' для #‹Enumerator::Lazy: #‹Enumerator::Lazy: [DiscountCode]›:map›` при попытке использовать lazy, как описано. - person Rebecca Meritz; 20.07.2018
comment
@RebeccaMeritz: Вы абсолютно правы, и я понятия не имею, почему никто не поправил меня раньше. Отредактировано. - person Amadan; 22.07.2018