web-dev-qa-db-ja.com

`Range#include?`と `Range#cover?`の違いは何ですか?

編集次のtro2kのコメントを修正しました。

Range#include?Range#cover?は、ソースコードに見られるように異なっているようです 12 、そしてそれらは効率が異なります。

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?のエイリアスにできないのはなぜですか?それらの違いは何ですか?

37
sawa

2つの方法は、意図的に2つのわずかに異なることを行うように設計されています。内部的には、実装方法も大きく異なります。 documentation のソースを見ると、.include?.cover?よりもはるかに多くのことを行っていることがわかります。

.cover?メソッドはComparableモジュールに関連しており、ソートされたリストのエンドポイントの間にアイテムが収まるかどうかをチェックします。アイテムがRangeによって示されるセットに含まれていない場合でも、trueを返します。

.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')
53
Neil Slater

主な違いは、includeはオブジェクトが範囲要素の1つであるかどうかをチェックし、coverはオブジェクトがエッジ要素の間にあるかどうかを返すことです。あなたはそれを見ることができます:

('a'..'z').include?('cc')     #=> false
('a'..'z').cover?('cc')       #=> true
10
BroiSatse
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を返すべきではありませんか?

私が尋ねている理由は、私がincludeを使用するときにrubocopが競合にフラグを立てることです。カバーの代わりに?そして明らかに、私のロジック(範囲が別の範囲に含まれているかどうかを確認するため)はカバーでは機能しませんか?.

0
Naveen N