发表于:2006.02.24 19:28
分类: Ruby学习
出处:http://my4java.itpub.net/post/9983/55333
---------------------------------------------------------------
Range对象表现为一个间隔,有开始与结束的值集。Range对象可以由范围操作符s..e及s…e字面值,或者用Range::new构建。由..操作符构建的Range对象包括范围的终点end值,而由…操作符构建的Range对象不包括范围的终点end值。当用于迭代器对象时,Range对象返回序列内的每一个值。
例如:
for i in 1..5
…
end
生成从1到5的Range对象,然后对分别每个值进行迭代操作。
再如:
(-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 enddef succ #succ方法的定义
Xs.new(@length + 1) #生成新对象
enddef <=>(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 生成并返回一个从start到end间隔范围的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中的start与end对象。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, ' ' endproduces: 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 特性:取消了length和size方法。若确实需要的话,可以这样
p ("a" .. "z").to_a.size #=> 26 即可。






