Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a method in Ruby that does the opposite of find?

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

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

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

In other words, it would behave the same way as:

[a, b, c].reject(&:zero?).first
like image 711
Pablo B. Avatar asked Apr 29 '11 19:04

Pablo B.


People also ask

What is the opposite of include in Ruby?

exclude? is defined as ! include?, meaning it is the exact opposite of include? . See the source. This means that it works for Arrays and Hashes too, as well as for Strings.

What does .first mean in Ruby?

The first() is an inbuilt method in Ruby returns an array of first X elements. If X is not mentioned, it returns the first element only. Syntax: range1.first(X) Parameters: The function accepts X which is the number of elements from the beginning. Return Value: It returns an array of first X elements.

How do you know if a Ruby is not nil?

That's the easy part. In Ruby, you can check if an object is nil, just by calling the nil? on the object... even if the object is nil.

What is include in Ruby?

include? is a String class method in Ruby which is used to return true if the given string contains the given string or character.


3 Answers

There is not, but you could create one either the clean-ish 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 the horribly-amusing hack way:

class Proc
  def !
    proc{ |o,*a| !self[o,*a] }
  end
end

p a.find(&!(:zero?.to_proc))
#=> 2

...or the terse-but-terribly-dangerous way:

class Symbol
  def !
    proc{ |o,*a| !o.send(self,*a) }
  end
end

p a.find(&!:zero?)
#=> 2

But I'd advocate just skipping the tricky Symbol#to_proc usage and saying what you want:

p a.find{ |i| !i.zero? }
#=> 2
like image 177
Phrogz Avatar answered Oct 02 '22 01:10

Phrogz


As far as I can tell there is not a standard method to do this (given that find_all and reject reference each other, but find does not reference anything). If you need it frequently (especially if the reject is too slow) you can write your own

module Enumerable

  def first_reject(&block)
    find {|a| not (block.call(a)) }
  end

end
like image 36
Kathy Van Stone Avatar answered Oct 02 '22 02:10

Kathy Van Stone


If you're using Ruby 2.0, you may be able to do lazy.reject(&:zero?).first without the performance penalty of going through the full array.

like image 25
Andrew Grimm Avatar answered Oct 02 '22 01:10

Andrew Grimm