“ . .”(双点)和“ ...”(三点)在范围生成上的区别?

我刚刚开始学习 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 中做了一些测试,它似乎表明 ..包含两个端点,而 ...只包含下界,而不包含上界。是这样吗?

68119 次浏览

没错。

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

表示一个范围。

只要看看它的内涵:

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

范围的文件说:

使用 ..构建的范围从头到尾都包括在内。使用 ...创建的范围不包括结束值。

所以 a..ba <= x <= b,而 a...ba <= x < b


请注意,当整数 Range 上的 to_a给出一个整数集合时,Range 是 没有一组值,但只是一对起始/结束值:

(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 (见下文)注意到这个更新。

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"]

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]