范围表示两个值之间的区间。
最常见的支持范围的类型是Integer和String。
它们有很多用途,比如快速创建集合、切分字符串、检查某个值是否在范围内,以及迭代。
范围使用运算符..或...创建(分别表示包含和不包含末尾值)。
1..5 # => 1..5
1...5 # => 1...5
(1..5).to_a # => [1, 2, 3, 4, 5]
(1...5).to_a # => [1, 2, 3, 4]
之所以要有两种范围运算符,是为了让你能创建包含或不包含末尾值的范围。比如在处理从 0 开始的下标时,这一点就很有用。
也可以用Range初始化器来创建范围。
Range.new(1, 5) # A range containing 1, 2, 3, 4, 5
在 Ruby 中用范围运算符..或...创建范围,并想在这个范围上调用方法时,需要把范围用括号括起来。
这是因为,如果不这样做,方法就会被调用在范围运算符的第二个参数上。
(1..5).sum # => 15
1..5.sum # => Error: undefined method `sum' for 5:Integer (NoMethodError)
想切分字符串时,可以用范围运算符来获取子字符串。 也就是用子字符串的起始和结束下标创建一个范围。
"Hello World"[0..4] # => "Hello"
"Hello World"[6..10] # => "World"
你也可以使用负数下标,从字符串末尾开始获取子字符串。
"Hello World"[-5..-1] # => "World"
"Hello World"[6..-4] # => "Wo"
范围自带一组可用于操作它们的方法。 例如,可以用这些方法求范围内所有值的和,或者检查范围是否包含某个值。
| 方法 | 说明 | 示例 |
|---|---|---|
sum |
返回范围内所有值的和 | (1..5).sum # => 15 |
size |
返回范围的大小 | (1..5).size # => 5 |
include? |
如果范围包含给定的值则返回true,否则返回false
|
(1..5).include?(3) # => true |
范围可以没有终点,也可以没有起点。
无终点或无起点的范围,其起点或终点值是nil,但在定义范围时,这个nil可以省略。
无终点范围和无起点范围很有用,比如当你想要从字符串开头切分,或者切分到字符串末尾时。
"Hello World"[0..] # => "Hello World"
"Hello World"[4..] # => "o World"
"Hello World"[..5] # => "Hello "
如果不是作用在集合上,无终点范围在不谨慎使用的情况下可能会产生无限序列。
字符串也可以用在范围中,让你得到两个字符串之间的一段字符串区间。 使用某些字符串时,它的行为可能有些出人意料,所以要谨慎使用。
"aa".."az".to_a # => ["aa", "ab", "ac", ..., "az"]
Ruby 允许你在范围中使用自定义对象。 前提是该对象实现了以下内容:
Comparable模块succ方法<=>方法有了这些方法,范围就能迭代该对象,并比较范围内的对象。
class Foo
include Comparable
attr_reader :value
def initialize(value)
@value = value
end
def succ
Foo.new(value + 1)
end
def <=>(other)
value <=> other.value
end
end
(Foo.new(1)..Foo.new(5))
# => #<Foo:0x7f3552bebe70 @value=1>, #<Foo:0x7f3552bebe50 @value=2>, #<Foo:0x7f3552bebe40 @value=3>, #<Foo:0x7f3552bebe30 @value=4>, #<Foo:0x7f3552bebe20 @value=5>