类 Range

Range 对象表示给定开始值和结束值之间的一系列值。

你可以使用以下方式显式创建一个 Range 对象

无始范围

一个无始范围 有一个确定的结束值,但开始值为 nil。这样的范围包括所有直到结束值的值。

r = (..4)               # => nil..4
r.begin                 # => nil
r.include?(-50)         # => true
r.include?(4)           # => true

r = (...4)              # => nil...4
r.include?(4)           # => false

Range.new(nil, 4)       # => nil..4
Range.new(nil, 4, true) # => nil...4

无始范围可用于切片数组

a = [1, 2, 3, 4]
# Include the third array element in the slice
r = (..2)  # => nil..2
a[r]       # => [1, 2, 3]
# Exclude the third array element from the slice
r = (...2) # => nil...2
a[r]       # => [1, 2]

无始范围的 each 方法会引发异常。

无终范围

一个无终范围 有一个确定的开始值,但结束值为 nil。这样的范围包括所有从开始值起的值。

r = (1..)         # => 1..
r.end             # => nil
r.include?(50)    # => true

Range.new(1, nil) # => 1..

无终范围的字面量可以用两个点或三个点来表示。两种方式表示的范围具有相同的元素。但请注意,两者不相等

r0 = (1..)           # => 1..
r1 = (1...)          # => 1...
r0.begin == r1.begin # => true
r0.end == r1.end     # => true
r0 == r1             # => false

无终范围可用于切片数组

a = [1, 2, 3, 4]
r = (2..) # => 2..
a[r]      # => [3, 4]

无终范围的 each 方法会无限期地调用给定的块

a = []
r = (1..)
r.each do |i|
  a.push(i) if i.even?
  break if i > 10
end
a # => [2, 4, 6, 8, 10]

一个范围可以既无始又无终。对于字面量的无始无终范围,至少范围的开始或结束必须显式地给出为 nil 值。建议使用显式的 nil 开始和隐式的 nil 结束,因为这是 Ruby 用于 Range#inspect 的方式

(nil..)    # => (nil..)
(..nil)    # => (nil..)
(nil..nil) # => (nil..)

范围与其他类

如果一个类的实例方法实现了 <=>,则可以将该类的对象放入范围中。这样做的 Ruby 核心类包括 ArrayComplexFile::StatFloatIntegerKernelModuleNumericRationalStringSymbolTime

示例

t0 = Time.now         # => 2021-09-19 09:22:48.4854986 -0500
t1 = Time.now         # => 2021-09-19 09:22:56.0365079 -0500
t2 = Time.now         # => 2021-09-19 09:23:08.5263283 -0500
(t0..t2).include?(t1) # => true
(t0..t1).include?(t2) # => false

只有当一个范围的元素实现了实例方法 succ 时,才能在该范围内进行迭代。这样做的 Ruby 核心类包括 IntegerStringSymbol(但不包括上面提到的其他类)。

迭代器方法包括

示例

a = []
(1..4).each {|i| a.push(i) }
a # => [1, 2, 3, 4]

范围与用户定义的类

要在范围中使用用户定义的类,该类必须实现实例方法 <=>;请参阅 Integer#<=>。要使迭代可用,它还必须实现实例方法 succ;请参阅 Integer#succ

下面的类同时实现了 <=>succ,因此既可以用于构造范围,也可以用于迭代范围。请注意,包含 Comparable 模块,因此 == 方法是根据 <=> 定义的。

# Represent a string of 'X' characters.
class Xs
  include Comparable
  attr_accessor :length
  def initialize(n)
    @length = n
  end
  def succ
    Xs.new(@length + 1)
  end
  def <=>(other)
    @length <=> other.length
  end
  def to_s
    sprintf "%2d #{inspect}", @length
  end
  def inspect
    'X' * @length
  end
end

r = Xs.new(3)..Xs.new(6) #=> XXX..XXXXXX
r.to_a                   #=> [XXX, XXXX, XXXXX, XXXXXX]
r.include?(Xs.new(5))    #=> true
r.include?(Xs.new(7))    #=> false

这里有什么

首先,其他地方有什么。类 Range

在这里,类 Range 提供了对以下内容有用的方法:

创建范围的方法

查询方法

比较方法

迭代方法

转换方法

使用 JSON 的方法

为了使这些方法可用

require 'json/add/range'