Range对象

Range 对象表现为一个间隔,有开始与结束的值集。 Range 对象可以由范围操作符 s..e s…e 字面值,或者用 Range::new 构建。由 .. 操作符构建的 Range 对象包括范围的终点 end 值,而由 操作符构建的 Range 对象不包括范围的终点 end 值。当用于迭代器对象时, Range 对象返回序列内的每一个值。

 

例如:

for i in 1..5

end

生成从 15Range 对象,然后对分别每个值进行迭代操作。

 

再如:

(-1..-5).to_a      
#=> []

(-5..-1).to_a      
#=> [-5, -4, -3, -2, -1]

('a'..'e').to_a    
#=> ["a", "b", "c", "d", "e"]

('a'...'e').to_a   
#=> ["a", "b", "c", "d"]

 

Range 对象可以由任何类型的对象构建,只要这个对象能够使用它们的 <=> 操作符,而且它们支持 succ 方法来返回序列内的下一个对象。也就是说,范围操作符的操作对象必须实现 <=> 比较操作,而且实现 succ 方法,则这个操作对象才能执行 Range#each 操作。

例如:

   

class Xs                
# 'x'
表示字符串

     
include Comparable

     
attr :length

     
def initialize(n)

       
@length = n

     
end

     
def succ              
#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.member?(Xs.new(5))       
#=> true

前面的例子中,类 Xs 包括了 Comparable 模块。这是因为 Enumerable#member? 使用 == 操作符检查等同性 (equality) 。包括 Comparable 可确保 == 操作符在实现 <=> 方法的 Xs 中被定义。

 

Range 类的超为是 Object ,同时它也包含了模块 Enumerable

 

类方法:

(1) Range.new(start, end, exclusive=false) => range 生成并返回一个从 startend 间隔范围的 Range 对象。第三个参数若省略或为 false ,则 Range 对象包含终点 end 对象,否则,不包含终点 end 对象。生成对象时,会执行 start <=> end 操作以检查参数的合法性。若返回 nil ,则引发 ArgumentError 异常。

 

实例方法:

(1) rng === obj => true or false rng.member?(val) => true or false rng.include?(val) => true or false val Range 对象 rng 的范围内则返回真。 === 主要用在 case 句的比较中。

case 79
   
when 1..50   
then   
print "lown"
   
when 51..75  
then   
print "mediumn"
   
when 76..100 then   
print "highn"
   
end

返回: high

p (0.1 .. 0.2).include?(0.15) # => true

p (0.1 .. 0.2).member?(0.15) # => cannot iterate from Float (TypeError)

 

# 比较字符串时, include? 将按照字典顺序进行比较

p ("a" .. "c").include?("ba") # => true

p ("a" .. "c").member?("ba") # => false

 

(2) rng.first => obj rng.begin => obj rng.end => obj rng.last => obj 返回 rng 中的 startend 对象。 last 的返回值与 Range 对象是否包含范围的终点无关。

p (1.. 5).end # => 5

p (1... 5).end # => 5

(3) rng.exclude_end? => true or false rng 对象不包含范围终点时返回真。

 

(4) rng.each {| i | block } => rng rng 对象的每个元素上进行迭代操作,传递每个值到 block 块中。你只可以在 Range 对象范围内的对象支持 succ 方法时进行迭代。 ( 这句话的意思是你不可以使用 Float 对象,因为它没有实现 succ 方法 )

Range#each 使用各元素的 succ 方法进行迭代操作。截止 1.6 版本为止,对 Numeric 对象一直采用的是算术运算。正因为作出了这个变更,所以不得不修改 Float 中的 Range 的处理方法。 (Float 没有 succ)

   

(10..15).each do |n|

      
print n, ' '

  
  
end

produces: 10 11 12 13 14 15

 

(5) rng.step(n=1) {| obj | block } => rng step 为步长对范围内的元素进行迭代操作。向 block 块传递每个 nth 元素。如果 Renge 对象的范围包含数字或字符串,则使用自然次序。否则 step 将调用 succ 方法来对范围内的元素进行迭代。 step 是正整数。默认值为 1

下面代码使用了前面的类 Xs

   

range = Xs.new(1)..Xs.new(10)

   
range.step(2) {|x| puts x}

   
range.step(3) {|x| puts x}

produces:

    
1 x

    
3 xxx

    
5 xxxxx

    
7 xxxxxxx

    
9 xxxxxxxxx

    
1 x

    
4 xxxx

    
7 xxxxxxx

   
10 xxxxxxxxxx

再如: ("a" .. "f").step(2) {|v| p v} # => "a" "c" "e"

 

(6) rng.to_s => string rng.inspect => string ruby 1.7 特性 :取消了 lengthsize 方法。若确实需要的话,可以这样

p ("a" .. "z").to_a.size #=> 26 即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值