В чем разница между "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?
В чем их отличие?
Ответы
Ответ 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? вместо покрытия?. И ясно, что моя логика (чтобы проверить, включен ли диапазон в другой диапазон) не работает с обложкой?.