Is there a Ruby method that does the opposite of searching?

a, b, c = 0, 1, 2 [a, b, c].find(&:zero?) # => 0 

Is there any method that will find the first element for which the block returns false?

 [a, b, c].the_method(&:zero?) # => 1 

In other words, it will behave in the same way as:

 [a, b, c].reject(&:zero?).first 
+6
source share
3 answers

There is not , but you can create it either in a clean way:

 a = [0,2,1,0,3] module Enumerable def first_not(&block) find{ |x| !block[x] } end end p a.first_not(&:zero?) #=> 2 

... or an awfully fun way of hacking:

 class Proc def ! proc{ |o,*a| !self[o,*a] } end end p a.find(&!(:zero?.to_proc)) #=> 2 

... or a complicated but terribly dangerous way:

 class Symbol def ! proc{ |o,*a| !o.send(self,*a) } end end p a.find(&!:zero?) #=> 2 

But I would advocate just skipping the complicated use of Symbol#to_proc and saying what you want:

 p a.find{ |i| !i.zero? } #=> 2 
+9
source

As far as I can tell, there is no standard method for this (given that find_all and reject each other’s link, but find doesn’t link anything). If you need it often (especially if the deviation is too slow), you can write your own

 module Enumerable def first_reject(&block) find {|a| not (block.call(a)) } end end 
+2
source

If you are using Ruby 2.0, you can do lazy.reject(&:zero?).first without penalty for passing through a full array.

+2
source

Source: https://habr.com/ru/post/886981/


All Articles