Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between `Range#include?` and `Range#cover?`?

Tags:

range

ruby

Edit Fixed following toro2k's comment.

Range#include? and Range#cover? seem to be different as seen in the source code 1, 2, and they are different in efficiency.

t = Time.now 500000.times do     ("a".."z").include?("g") end puts Time.now - t    # => 0.504382493  t = Time.now 500000.times do     ("a".."z").cover?("g") end puts Time.now - t    # => 0.454867868 

Looking at the source code, Range#include? seems to be more complex than Range#cover?. Why can't Range#include? be simply an alias of Range#cover? What is their difference?

like image 542
sawa Avatar asked Feb 06 '14 16:02

sawa


1 Answers

The two methods are designed to do two slightly different things on purpose. Internally they are implemented very differently too. You can take a look at the sources in the documentation and see that .include? is doing a lot more than .cover?

The .cover? method is related to the Comparable module, and checks whether an item would fit between the end points in a sorted list. It will return true even if the item is not in the set implied by the Range.

The .include? method is related to the Enumerable module, and checks whether an item is actually in the complete set implied by the Range. There is some finessing with numerics - Integer ranges are counted as including all the implied Float values (I'm not sure why).

These examples might help:

('a'..'z').cover?('yellow') # => true  ('a'..'z').include?('yellow') # => false  ('yellaa'..'yellzz').include?('yellow')  => true 

Additionally, if you try

('aaaaaa'..'zzzzzz').include?('yellow') 

you should notice it takes a much longer time than

('aaaaaa'..'zzzzzz').cover?('yellow') 
like image 151
Neil Slater Avatar answered Sep 26 '22 21:09

Neil Slater