Разница между '..' (двойная точка) и '...' (тройная точка) в генерации диапазона?
Я только начал изучать Ruby и Ruby on Rails и наткнулся на код проверки, который использует диапазоны:
validates_inclusion_of :age, :in => 21..99
validates_exclusion_of :age, :in => 0...21, :message => "Sorry, you must be over 21"
Сначала я думал, что разница заключается во включении конечных точек, но в документах по API, которые я изучал, казалось, не имеет значения, было ли это ..
или же ...
: это всегда включало конечные точки.
Тем не менее, я провел некоторое тестирование в irb, и, похоже, это ..
включает в себя обе конечные точки, в то время как ...
включает только нижнюю границу, но не верхнюю. Это правильно?
5 ответов
Документация для Range † гласит:
Диапазоны построены с использованием
..
бегать от начала до конца включительно. Те, созданные с использованием...
исключить конечное значение.
Так a..b
как a <= x <= b
, в то время как a...b
как a <= x < b
,
Обратите внимание, что в то время как to_a
для диапазона целых чисел дает коллекцию целых чисел, диапазон - это не набор значений, а просто пара начальных / конечных значений:
(1..5).include?(5) #=> true
(1...5).include?(5) #=> false
(1..4).include?(4.1) #=> false
(1...5).include?(4.1) #=> true
(1..4).to_a == (1...5).to_a #=> true
(1..4) == (1...5) #=> false
† Документы раньше не включали это, вместо этого требовали прочтения раздела Кирки на Рэнджах. Спасибо @MarkAmery ( см. Ниже) за то, что отметили это обновление.
Это правильно.
1.9.3p0 :005 > (1...10).to_a
=> [1, 2, 3, 4, 5, 6, 7, 8, 9]
1.9.3p0 :006 > (1..10).to_a
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Синтаксис с тройными точками встречается реже, но лучше, чем (1..10-1).to_a
Документы API теперь описывают это поведение:
Диапазоны построены с использованием
..
бегать от начала до конца включительно. Те, созданные с использованием...
исключить конечное значение.
Другими словами:
2.1.3 :001 > ('a'...'d').to_a
=> ["a", "b", "c"]
2.1.3 :002 > ('a'..'d').to_a
=> ["a", "b", "c", "d"]
a...b
исключает конечное значение, в то время как a..b
включает в себя конечное значение.
При работе с целыми числами, a...b
ведет себя как a..b-1
,
>> (-1...3).to_a
=> [-1, 0, 1, 2]
>> (-1..2).to_a
=> [-1, 0, 1, 2]
>> (-1..2).to_a == (-1...3).to_a
=> true
Но на самом деле диапазоны различаются на вещественной числовой линии.
>> (-1..2) == (-1...3)
=> false
Вы можете увидеть это при увеличении дробными шагами.
>> (-1..2).step(0.5).to_a
=> [-1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0]
>> (-1...3).step(0.5).to_a
=> [-1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, 2.5]
.. и... обозначают диапазон.
Просто посмотрите на это в irb:
ruby-1.9.2-p290 :032 > (1...2).each do puts "p" end
p
=> 1...2
ruby-1.9.2-p290 :033 > (1..2).each do puts "p" end
p
p