Подтвердить что ты не робот

В чем разница между "Range # include?" И "Range # cover?"?

Изменить Исправлено следующее комментарий toro2k.

Range#include? и Range#cover? кажутся разными, как показано в исходном коде 1, 2, и они отличаются по эффективности.

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

Рассматривая исходный код, Range#include? представляется более сложным, чем Range#cover?. Почему Range#include? не может быть просто псевдонимом Range#cover? В чем их отличие?

4b9b3361

Ответ 1

Два метода предназначены для того, чтобы сделать две несколько разные вещи. Внутренне они реализованы совсем по-другому. Вы можете посмотреть источники в документации и увидеть, что .include? делает намного больше, чем .cover?

Метод .cover? связан с модулем Comparable и проверяет, будет ли элемент располагаться между конечными точками в отсортированном списке. Он вернет true, даже если элемент не находится в наборе, подразумеваемом Range.

Метод .include? связан с модулем Enumerable и проверяет, действительно ли элемент находится в полном наборе, подразумеваемом Range. Существует ряд уловок с числами. Целочисленные диапазоны учитываются как включающие все подразумеваемые значения Float (я не уверен, почему).

Эти примеры могут помочь:

('a'..'z').cover?('yellow')
# => true

('a'..'z').include?('yellow')
# => false

('yellaa'..'yellzz').include?('yellow')
 => true

Кроме того, если вы попытаетесь выполнить

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

вы должны заметить, что это занимает гораздо больше времени, чем

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

Ответ 2

Основное отличие состоит в том, что include проверяет, является ли объект одним из элементов диапазона, а обложка возвращает, находится ли объект между крайними элементами. Вы можете видеть, что:

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

Должна ли последняя строка возвращать true?

Причина, по которой я спрашиваю, - это rubocop означает конфликт, когда я использую include? вместо покрытия?. И ясно, что моя логика (чтобы проверить, включен ли диапазон в другой диапазон) не работает с обложкой?.