2014-02-06 2 views
27

Редактировать Исправлено сообщение с комментатором toro2k.В чем разница между `Range # include?` И `Range # cover?`?

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? В чем их отличие?

+0

Я тоже был озадачен этим. См. Мой [ответ здесь] (http://stackoverflow.com/questions/21507117/select-arrays-between-date-ranges-with-ruby/21507252#21507252). –

ответ

34

Эти два метода предназначены для того, чтобы сделать две разные вещи. Внутренне они реализованы совсем по-другому. Вы можете посмотреть на источники в documentation и видим, что .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') 
+3

Я вижу. Итак, теперь мне кажется, что «Range # include?» Очень таинственный. – sawa

6

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

('a'..'z').include?('cc')  #=> false 
('a'..'z').cover?('cc')  #=> true 
0
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   

Не следует последняя строка возвращает истину?

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

Смежные вопросы