Ruby ';之间的差异';(双点)和'';(三点)范围内生成?

Ruby ';之间的差异';(双点)和'';(三点)范围内生成?,ruby,syntax,range,Ruby,Syntax,Range,我刚刚开始学习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中做了一些测试,它似乎表明。包括两个端点

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

这是正确的

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)更好。。而且。。。表示一个范围

请在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
该†表示:

使用
构建的范围。
从头到尾运行。使用
创建的值不包括结束值


因此
a..b
就像
aAPI文档现在描述了这种行为:

使用
构建的范围。
从头到尾运行。使用
创建的值不包括结束值

--

换言之:

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).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]

我认为更多的点意味着范围代表更少的值,这真的很奇怪。我想这只是因为
更常见,因此不太受欢迎?@Andrew:我也这么认为,但可能是因为双点类型更常见,因此打字更短?另外,请注意
(a..b-1)!=(a…b)
,尽管这个答案暗示它们是。(a…b-1)==(a…b)仅在a和b是整数并且将范围枚举到数组的情况下。考虑范围(1…3.5)-在3.5之前的值是多少?当然不是2.5!但这并不能真正回答这个问题;两者都被描述为范围。包含与排除范围。编辑后仍然不正确。即使
a
b
是整数,范围也不同。只有当每个都转换为数组时,它们才是相同的。一个具体的反例存在于被接受的答案中。@AndrewMarshall我对这个例子的意思(但显然不是很清楚)是在一个整数范围内,它的行为就是这样的。正如你在回答中指出的,在更精确的分数尺度上,情况并非如此。我认为范围通常是在整数范围内使用的,这就是为什么我认为这样的解释是有帮助的。比上面的例子更好/更容易混淆:
(1..10)。包括?10#=>正确
(1…10)。包括?10#=>假
@timmcliu尽管与说明
(a..b)!=(a…(b+1))
尽管它们的数组表示形式相等(当a,b∈ ℤ). 我更新了我的答案来扩展它。如果Range不是一组值,那么为什么这段代码将Range视为一组值:(1..5)@ValentinVassilev Range不是一组值,但它可以生成它们。
inject
来自
Range
包含的;
Enumerable
利用
#each
,这一点。由
Range#each
生成的列表从不包含在
范围
对象本身中。Oof,与Swift、D、R正好相反乌斯特,C#。。。
>> (-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]