Різниця між ".." (двокрапкою) та "..." (потрійною точкою) у поколінні діапазону?


111

Я щойно почав вивчати Ruby і Ruby на Rails і натрапив на код перевірки, який використовує діапазони:

validates_inclusion_of :age, :in => 21..99
validates_exclusion_of :age, :in => 0...21, :message => "Sorry, you must be over 21"

Спочатку я думав, що різниця полягає у включенні кінцевих точок, але в документах API, які я розглядав, здавалося, не важливо, чи це .. чи ...: завжди включені кінцеві точки.

Однак я провів тестування в irb, і, здавалося, це вказує на те, що ..включає обидві кінцеві точки, в той час ...як включає лише нижню межу, але не верхню. Це правильно?

Відповіді:


157

Документація Діапазон каже , що це:

Діапазони, побудовані за допомогою ..запуску від початку до кінця включно. Створені за допомогою ...виключають кінцеве значення.

Так 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


Документи, які раніше не включали це, замість цього вимагали прочитати розділ Pickaxe про Діапазони . Дякуємо @MarkAmery ( див. Нижче ) за те, що помітили це оновлення.


11
Кращий / менш заплутаний приклад, ніж вище: (1..10).include? 10 #=> trueта(1...10).include? 10 #=> false
timmcliu

@timmcliu Хоча це не стосується ілюстрування точки, яка, (a..b) != (a...(b+1))незважаючи на те, що їхні представлення масиву рівні (коли a, b ∈ ∈). Я трохи оновив свою відповідь, щоб розширити це питання.
Ендрю Маршалл

Якщо діапазон не є набором значень, то чому цей фрагмент коду трактує діапазон як набір значень: (1..5) .inject {| сума, n | sum + n}
VaVa

2
Діапазон @ValentinVassilev не є набором значень, але він може їх генерувати. injectпоходить від Enumerableчого Rangeвключає; Enumerableвикористовує #each, що Rangeреалізує . Список, що генерується, Range#eachніколи не міститься в самому Rangeоб'єкті.
Ендрю Маршалл

6

Це правильно.

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


12
Я думаю, що це дійсно химерно, що більше крапок означає, що діапазон представляє менше значень. Я здогадуюсь, що саме це ..є більш поширеним, і, отже, менше надається переваги?
Ендрю Маршалл

2
@Andrew: Я думав, що теж, але, можливо, справа в тому, що двоточковий різновид є частіше бажаним і, таким чином, коротшим для введення?
безпечна копія

1
Також зауважте (a..b-1) != (a...b), хоча ця відповідь означає, що вони є.
Ендрю Маршалл

1
(a..b-1) == (a ... b) лише у тому випадку, коли a і b цілі числа, і ви перераховуєте діапазони в масиви. Розглянемо діапазон (1,0 ... 3,5) - яке значення безпосередньо перед 3,5? Звичайно не 2,5!
Кріс Хілд

3

Документи API тепер описують таку поведінку:

Діапазони, побудовані за допомогою ..запуску від початку до кінця включно. Створені за допомогою ...виключають кінцеве значення.

- http://ruby-doc.org/core-2.1.3/Range.html

Іншими словами:

2.1.3 :001 > ('a'...'d').to_a
 => ["a", "b", "c"] 
2.1.3 :002 > ('a'..'d').to_a
 => ["a", "b", "c", "d"] 

1

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]

1
Після редагування все ще неправильно. Навіть якщо a& bцілі числа, діапазони різні. Тільки коли кожен перетворюється в масив, вони однакові. У прийнятій відповіді існує конкретний контрприклад.
Ендрю Маршалл

2
@AndrewMarshall Те, що я мав намір сказати на цьому прикладі (але не дуже добре, очевидно), є в цілому масштабі, воно так поводиться. Це не так у більш точній дробній шкалі, як зазначено у вашій відповіді. Я вважаю, що діапазони найчастіше використовуються в цілому масштабі, тому я вважаю, що таке пояснення є корисним.
Денніс

-4

.. і ... позначають діапазон.

Просто побачите це в 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

2
Але насправді не відповідає на питання; обидва описуються діапазонами. Інклюзивний проти Ексклюзивний асортимент
Крейг Рінгер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.