Programming Ruby(读书笔记)-6章(标准类型)

前面几章已涉及Array,Hash,Proc三种Ruby提供的类型。这章我们会涉及:numbers,strings,ranges及正则表达式。

 

6.1 数值类型

Ruby支持integers(整数),floating-point浮点型),rational(有理数),complex numbers(复数)。整型可是任意长度(内存空间的长度),超出正常整型的部分存储类型是Bignum的实例,不超出部分是Fixnum的实例,这种转换Ruby自动转换.

#当超出正常范围后,自动使用Bignum
num = 10001
4.times do
  puts "#{num.class}: #{num}"
num *= num
end
produces:
Fixnum: 10001
Fixnum: 100020001
Fixnum: 10004000600040001
Bignum: 100080028005600700056002800080001

 前缀标识几进制表示:0-八进制 0d-十进制 0x-十六进制 0b-二进制

123456      => 123456 # Fixnum
0d123456  => 123456 # Fixnum
123_456    => 123456 # Fixnum - underscore ignored
-543           => -543 # Fixnum - negative number
0xaabb      => 43707 # Fixnum - hexadecimal
0377          => 255 # Fixnum - octal
-0b10_1010 => -42 # Fixnum - binary (negated)
123_456_789_123_456_789 => 123456789123456789 # Bignum
#下划线被约定为.的转换,所以自动去掉。

 数字串如果包含(decimal point)小数点或(exponent)指数,则将被转换为Float对象。

1.0e3不可以省去.后的1.e3,因为这样会去调用1对象的e3方法。所认.后面必需跟一个数值。

 

有理数是两个整数的比,复数也有实数与虚数。这两个都不能用一个串的样式表示,Ruby提供Rational与Complex两个类,调用它们的构造方法,即获取对象。

Rational(3, 4) * Rational(2, 3) # => (1/2)
Rational("3/4") * Rational("2/3") # => (1/2)

Complex(1, 2) * Complex(3, 4) # => (-5+10i)
Complex("1+2i") * Complex("3+4i") # => (-5+10i)

所有的数值类型都是对象,提供了多个方法,比如num.abs就是获取它的绝对值。

#字符串类型不会自动转换为整型
some_file.each do |line|
  v1,v2 = line.split
  print Integer(v1) + Integer(v2), "  " #这里要显示的转换
end
produces:
7 11 15

 

How Numbers Interact(数值的内部原理)

操作符两边如果类型不一样,结果会采用更通用的那个类型来保存,比如混合整型与浮点型,则结果是浮点型,混合浮点型与复数,结果是复数。

除的规则也是一样,只是两个整型相除,结果还是整型:

1.0 / 2 # => 0.5
1 / 2.0 # => 0.5
1 / 2 # => 0

 如果引入了mathn模块,则可以使用22/7这种有理数结构表示。

 

循环数值类型

#类Numberic支持许多迭代方法,比如:
3.times { print "X "}
1.upto(5) {|i| print i, " "}
99.downto(95) {|i| print i, " "}
50.step(80, 5) {|i print i, " "|}

produces:
X X X 1 2 3 4 5 99 98 97 96 95 50 55 60 65 70 75 80

 迭代器如果没有跟{},则返回的是Enumerator对象。比如:

10.downto(7).with_index {|num, index| puts "#{index}: #{num}"}
produces:
0: 10
1: 9
2: 8
3: 7

 

6.2 strings

#与JS的引号规则一致
'escape using "\\"' # => escape using "\"
'That\'s right' # => That's right

 #{expr}表示希望被替代的值,如果expr是全局变量,类变量或实例变量,可以忽略。

# expr可以是表达式
"Seconds/day: #{24*60*60}" # => Seconds/day: 86400
"#{'Ho! '*3}Merry Christmas!" # => Ho! Ho! Ho! Merry Christmas!
"Safe level is #$SAFE" # => Safe level is 0
#字符与数值相乘,则表示重复多少次
#$SAFE被表示为了0

 插入串不仅可以是表达式,还可以是一个或多个代码段:

puts "now is #{ def the(a)
                              'the' + a
                           end
                           the('time')
                         } for all bad coders..."
produces:
now is the time for all bad coders...

 还可使用%q %Q here标注来构造字符串。

%q/general single-quoted string/ # => general single-quoted string
%Q!general double-quoted string! # => general double-quoted string
%Q{Seconds/day: #{24*60*60}} # => Seconds/day: 86400
q与Q也是可以省略的
%!general double-quoted string! # => general double-quoted string
%{Seconds/day: #{24*60*60}} # => Seconds/day: 86400
#%q相当于单引号,%Q相当于双引号。
#q与Q后面跟分割符,如果是[ { (,则结束符是] } ),否则结束符是相同的符号。

 ---------------using a here document-----------

#通过END_OF_STRING标识为终结符,注意终结符应该放在第一列
string = <<END_OF_STRING
The body of the string is the input lines up to
one starting with the same text that followed the '<<'
END_OF_STRING #这个要放在第一列

 如果<<后面添加一个-,就可以不用遵循放在第一列的规则

string = <<-END_OF_STRING
            The body of the string is the input lines up to
            one starting with the same text that followed the '<<'
            END_OF_STRING

 也可以有多个here document

print <<-STRING1, <<-STRING2
Concat
STRING1
       enate
       STRING2

produces:
Concat
      enate

 注意:空格不会自动trip掉

 

Strings And Encodings

1.9默认的是US-ASCII,2.0默认是UTF-8

#打印字符编码
plain_string = "dog"
puts RUBY_VERSION
puts "Encoding of #{plain_string.inspect} is #{plain_string.encoding}"

 

Working with Strings

下面的示例描述使用String的方法。假设有这样一个数据文件:

ut_stdtypes/songdata
song’s duration, the artist, and the title
/jazz/j00132.mp3  | 3:45 | Fats Waller         | Ain't Misbehavin'
/jazz/j00319.mp3  | 2:58 | Louis Armstrong     | Wonderful World
/bgrass/bg0732.mp3| 4:09 | Strength in Numbers | Texas Red

 假设需求有三:

  1. 将第一行数据填充到对应的属性中
  2. 将以mm:ss格式的时间转换为秒
  3. 将属性内容的空格trip掉
#下面示例演示上面需求实现的代码
#String#chomp用于去掉串后的分离符如\r\n
#String#squeeze用于去掉重复的字符 !在本串操作?

Song = Struct.new(:title, :name, :length)

File.open("songdata") do |song_file|
  songs = []
  song_file.each do |line|
    file, length, name, title = line.chomp.split(/\s*\|\s*/)
	name.squeeze!(" ")
	mins, secs = length.scan(/\d+/)
	songs << Song.new(title, name, mins.to_i*60 + secs.to_i)
  end
  
  puts songs[1]
end

 

6.3 Ranges(范围)

三个主要用途:sequences(序列),conditions(条件),intervals(区间)

 

Ranges as Sequences

1..10
'a'..'z'
0...'cat'.length
#..包含开始与结束;...不包含结束(高位)
#转换range,调用to_a转换为数组,to_enum转换为Enumerator
(1..10).to_a # => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
('bar'..'bat').to_a # => ["bar", "bas", "bat"]
enum = ('bar'..'bat').to_enum
enum.next # => "bar"
enum.next # => "bas"
############
#Range提供方法迭代它的内容,或者测试这些内容
digits = 0..9 #定义一个Range
digits.include?(5) # => true
digits.max # => 9
digits.reject {|i| i < 5 } # => [5, 6, 7, 8, 9]
digits.inject(:+) # => 45

 我们可以让自己定义的类支持Range的这种sequence用途,所要做的是实现succ方法返回下一个对象,以及<=>方法,这个类似于compare接口。

class PowerOfTwo
  attr_reader :value
  def initialize(value)
    @value = value
  end
  def <=>(other)
    @value <=>other.value
  end
  def succ
    PowerOfTwo.new(@value + @value)
  end
  def to_s
    @value.to_s
  end
end
p1 = PowerOfTwo.new(4)
p2 = PowerOfTwo.new(32)
puts (p1..p2).to_a
produces:
4
8
16
32

 

Ranges as Conditions

 

#这个示例用于读取第一行包含start,最后一行包含end
while line=gets
  puts line if line=~/start/..line=~/end/
end
 

 

Ranges as Intervals

测试元素是在指定的区间。使用===操作符

 

(1..10) === 5       # => true
(1..10) === 15      # => false
(1..10) === 3.14159 # => true
('a'..'j') === 'c'  # => true
('a'..'j') === 'z'  # => false

 

#假设输入的是9.5
car_age = gets.to_f
case car_age
when 0...1
  puts "Mmm.. new car smell"
when 1...3
  puts "Nice and new"
when 3...10
  puts "Reliable but slightly dinged"
when 10...30
  puts "Clunker"
else
  puts "Vintage gem"
end

produces:
Reliable but slightly dinged

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值