`
simohayha
  • 浏览: 1395897 次
  • 性别: Icon_minigender_1
  • 来自: 火星
社区版块
存档分类
最新评论

ruby way之Ranges

    博客分类:
  • ruby
阅读更多
1   1个简单的数字区间我们能这样表示:

 digits = 0..9
scale1 = 0..10
scale2 = 0...10


其中..包括结束点,...不包括结束点,也就是说digits和scale2的表示范围是一样的.

在ruby中,不只是数值可以用作区间,任何ruby对象都可以用作区间。可是并不是所有的表示都有意义或者有用。

接下来让我们来看看怎么操作区间:

2 开区间和闭区间

就像上面说的,..是闭区间,...是开区间:
r1 = 3..6     # closed
r2 = 3...6    # open
a1 = r1.to_a  # [3,4,5,6]
a2 = r2.to_a  # [3,4,5]


我们没有任何方法来去除掉开始点,这是语言的限制,所以我们这只能说是半开区间.

3 得到终点

first和last方法返回一个区间的开始和结束点:

r1 = 3..6
r2 = 3...6
r1a,r1b = r1.first,r1.last    # 3, 6
r1c,r1d = r1.begin,r1.end     # 3, 6
r2a,r2b = r2.begin,r2.end     # 3, 6

puts r1a,r1b,r1c,r1d,r2a,r2b


这边要注意不论是开区间还是闭区间,last和end都会返回它本身的结束点.

exclude_end? 方法告诉我们是否一个区间是否是开的:

r1.exclude_end?   # false
r2.exclude_end?   # true


4迭代一个区间

我们要是想要一个迭代成功,那么区间的元素必须定义了一个有意义的succ方法:

(3..6).each {|x| puts x }  # prints four lines


这里要注意的是,当处理字符串的区间的时候。尽管String类定义了succ方法,可是他是一个受限制的。因为string的succ方法的定义并不是很严格,我们先看下面的例子:

r1 = "7".."9"
r2 = "7".."10"
r1.each {|x| puts x }   # Prints three lines
r2.each {|x| puts x }   #什么都没有输出


r1,r2看起来没有什么不同,可是打印出的结果却是大相径庭。我们再仔细看,r2的结束点字符"10"的长度是2,和这个区间内的其他字符的长度是不一样的。

当我们尝试着迭代r2的时候,我们开始于字符"7",当下一个字符大于大于右边的结束点时,我们退出循环。但是“7”和“10”现在是字符而不是数字。他们之间的比较是按字典的顺序,然后我们就发现"7"比"10"大,因此r2就不会打印出任何东西.

这边要注意我们不能迭代一个浮点数的区间:

fr = 2.0..2.2
fr.each {|x| puts x }   # error!


为什么浮点数没有succ方法呢?一个浮点数区间,每次增加一个浮点数字,只是理论上可行的。因为这个技术有很强的机器相关性,有时会在迭代一个很小的区间时,出现很大的数字,因此我们这样做了。

5 测试是否在区间内

我们使用include?方法来测试一个是否在区间:

r1 = 23456..34567
x = 14142
y = 31416
r1.include?(x)      # false
r1.include?(y)      # true


member?方法是include?方法的别名。

include?方法内部是怎么样工作的呢,它是依据什么来判断的呢?在这里inculde?方法是依据<=>方法来判断的.

也就是说(a..b).include?(x) 可以写成这样: x >= a and x <= b.

再次说一下,要小心字符区间:

s1 = "2".."5"
str = "28"
s1.include?(str)    # true (misleading!)


6转换成一个数组

当我们转换一个区间到一个数组时,他只是简单的使用succ方法,然后将区间里的每一个元素放进一个数组:

r = 3..12
arr = r.to_a     # [3,4,5,6,7,8,9,10,11,12]


他不能在浮点区间使用,字符区间有时可以使用,所以我们要避免这样做.

7 反向的区间

反向的区间也就是从大到小:
r = 6..3
puts x = r.begin              # 6
puts y = r.end                # 3
puts flag = r.exclude_end?  # false


反向区间也可以像一般区间那样操作:

arr = r.to_a       # []
r.each {|x| p x}   # No iterations
y = 5
puts r.include?(y)      # false (for any value of y)


反向区间最大的用途,是用在数组和字符中,因为在他们中左边的其实角标是0右边是-1:

string = "flowery"
str1   = string[0..-2]   # "flower"
str2   = string[1..-2]   # "lower"
str3   = string[-5..-3]  # "owe" (actually a forward range)



8flip-flop运算符

也就是把一个区间当作条件来进行操作。这个时候,这个区间就像是一个双态触发器。
这个的话,宝石书里面介绍的比较好,而且他还有图,大家可以看看那个就行了。

9自定义区间

class Roman
  include Comparable

  I,IV,V,IX,X,XL,L,XC,C,CD,D,CM,M =
    1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000

  Values = %w[M CM D CD C XC L XL X IX V IV I]

  def Roman.encode(value)
    return "" if self == 0
    str = ""
    Values.each do |letters|
      rnum = const_get(letters)
      if value >= rnum
        return(letters + str=encode(value-rnum))
      end
    end
    str
  end

  def Roman.decode(rvalue)
    sum = 0
    letters = rvalue.split('')
    letters.each_with_index do |letter,i|
      this = const_get(letter)
      that = const_get(letters[i+1]) rescue 0
      op = that > this ? :- : :+
      sum = sum.send(op,this)
    end
    sum
  end

  def initialize(value)
    case value
      when String
        @roman = value
        @decimal = Roman.decode(@roman)
      when Symbol
        @roman = value.to_s
        @decimal = Roman.decode(@roman)
      when Numeric
        @decimal = value
        @roman = Roman.encode(@decimal)
    end
  end

  def to_i
    @decimal
  end

  def to_s
    @roman
  end

  def succ
    Roman.new(@decimal+1)
  end

  def <=>(other)
    self.to_i <=> other.to_i
  end
end


这是一个我们自定义的区间,代码很好懂,这边主要要看的就是我们定义的succ方法,当我们使用Roman对象作为区间的时候,我们如果迭代他,就会自动调用succ方法,下面来看测试代码:

require 'roman'

y1 = Roman(:MCMLXVI)
y2 = Roman(:MMIX)
range = y1..y2                # 1966..2009
range.each {|x| puts x}       # 44 lines of output

epoch = Roman(:MCMLXX)
range.include?(epoch)         # true

doomsday = Roman(2038)
range.include?(doomsday)      # false

Roman(:V) == Roman(:IV).succ  # true
Roman(:MCM) < Roman(:MM)      # true
分享到:
评论

相关推荐

    The Ruby Way--3rd Edition--2015-英文版

    The Ruby Way 第三版(英文版),全书22章,书中包含600多个按主题分类的示例。每个示例都回答了“如何使用Ruby来完成”的问题。 ——Ruby on Rails之父David Heinemeier Hansson倾力推荐!

    The Ruby Way(第2版)

    The Ruby Way(第2版) &lt;br&gt;The Ruby Way assumes that the reader is already familiar with the subject matter. Using many code samples it focuses on "how-to use Ruby" for specific applications, either ...

    THE RUBY WAY(中文版)(第二版)pdf

    《The Ruby Way 第二版》...“《The Ruby Way (第2版)中文版》在阐述元编程(metaprogramming)等方面尤其出类拔萃,而元编程是Ruby最引人注目的方面之一。” ——Ruby on Rails之父David Heinemeier Hansson倾力推荐!

    the ruby way 2ed

    《The Ruby Way 2nd Edition》是一本深入探讨Ruby编程语言的经典著作,旨在帮助读者全面理解和掌握Ruby的精髓。这本书的第二版在2006年出版,由Addison-Wesley出版,作者通过深入浅出的方式,揭示了Ruby语言的强大...

    ruby学习资源(Programming Ruby, Learning Ruby, The Ruby Way)

    内含以下4个文档: 1、Addison.Wesley.The.Ruby.Way.2nd.Edition.Oct.2006.chm 2、O'Reilly.Learning.Ruby.May.2007.chm 3、Programming Ruby 2e.pdf 4、ruby中文文档.chm

    the-ruby-way

    the ruby way the ruby way

    11.5 时间日期the ruby way.rar

    "11.5 时间日期the ruby way"这个主题深入探讨了Ruby中处理时间日期的最佳实践和常见用法。让我们逐一了解这些知识点。 首先,`Time.now`是Ruby中获取当前时间的标准方法。它返回一个`Time`对象,表示自1970年1月1...

    the ruby way

    3. **块、proc和lambda**:Ruby中的块、Proc和Lambda是其独特之处,它们提供了强大的函数式编程特性,允许你编写更简洁、更灵活的代码。 4. **方法和元编程**:Ruby允许在运行时动态定义和修改方法,元编程能力使...

    Ruby-Way.rar_About Language

    《Ruby Way》是由Hal Fulton编写的关于Ruby编程语言的一本著作。这本书深入浅出地探讨了Ruby语言的各种特性,旨在帮助读者理解并掌握这门强大的动态脚本语言。Ruby以其简洁、优雅的语法和强大的元编程能力而备受赞誉...

    Addison Wesley The Ruby Way 2Nd Edition Oct 2006.pdf(英文版)

    ### Addison Wesley《The Ruby Way》第二版(2006年10月) #### 书籍概览 《The Ruby Way》是由Hal Fulton编写的关于Ruby编程语言的经典著作,该书的第二版出版于2006年10月,由Addison Wesley Professional出版社...

    Addison.Wesley.The.Ruby.Way.2nd.Edition.Oct.2006.chm

    《The Ruby Way》第二版是Addison-Wesley出版社在2006年推出的一本深入浅出的Ruby编程语言教程。这本书专为初学者设计,旨在帮助读者快速掌握Ruby语言的基础和高级特性,从而轻松入门Ruby编程。Ruby是一种动态、开放...

    The Ruby Way

    Ruby is a fully object-oriented, dynamic scripting language which borrows some of the best features from LISP, Smalltalk, Perl, CLU, and other languages, and blends them into a harmonious whole....

    Ruby Ruby Ruby Ruby Ruby Ruby

    Ruby Ruby Ruby Ruby Ruby Ruby

    ruby代码ruby代码ruby代码ruby代码ruby代码ruby代码

    ruby代码ruby代码ruby代码ruby代码ruby代码ruby代码ruby代码ruby代码

    ruby中英文api

    Ruby是一种面向对象的、动态类型的编程语言,以其简洁、优雅的语法著称,尤其适合Web开发,其中Rails框架是其最著名的应用之一。API(Application Programming Interface)是软件开发者用来与操作系统、库或服务进行...

Global site tag (gtag.js) - Google Analytics