EasyTime - Ruby学习笔记
自我介绍
切换风格
订阅我的Blog
博客日历
文章归档...
最新发表...
博客统计...
网站链接...
资源
===========================================================
Range对象
===========================================================

Range对象表现为一个间隔,有开始与结束的值集。Range对象可以由范围操作符s..es…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 即可。

my4java 发表于:2006.02.24 19:28 ::分类: ( Ruby学习 ) ::阅读:(718次) :: 评论 (0) :: 引用 (0)

发表评论
标题

在此添加评论

称呼

邮箱地址(可选)

个人主页(可选)

authimage