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

徘徊边缘 提交于 2019-11-27 04:35:40

问题


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?


回答1:


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')



回答2:


The main difference is that include is checking whether object is one of range element, and cover is returning whether object is between edge elements. You can see that:

('a'..'z').include?('cc')     #=> false
('a'..'z').cover?('cc')       #=> true



回答3:


date_range = {:start_date => (DateTime.now + 1.days).to_date, :end_date => (DateTime.now + 10.days).to_date}                
date_range_to_check_for_coverage = {:start_date => (DateTime.now + 5.days).to_date, :end_date => (DateTime.now + 7.days).to_date}                

(date_range[:start_date]..date_range[:end_date]).include?((DateTime.now + 5.days).to_date)                
#true        
(date_range[:start_date]..date_range[:end_date]).cover?((DateTime.now + 5.days).to_date)                
#true        
(date_range[:start_date]..date_range[:end_date]).include?(date_range_to_check_for_coverage[:start_date]..date_range_to_check_for_coverage[:end_date])                
#true        
(date_range[:start_date]..date_range[:end_date]).cover?(date_range_to_check_for_coverage[:start_date]..date_range_to_check_for_coverage[:end_date])                
#false        

Shouldn't the last line return true ?

The reason I am asking is rubocop flags a conflict when I use include? in place of cover?. And clearly, my logic (to check if the range is included in another range) does not work with cover?.



来源:https://stackoverflow.com/questions/21608935/what-is-the-difference-between-rangeinclude-and-rangecover

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!