问题
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