本章主要讲述三个内容:
- 什么是条件判断
- 条件判断中第比较运算符、真假值1、逻辑运算符
- 条件判断的种类及其写法和使用方法
5.1 什么是条件判断
条件判断语句有以下三种:
- if语句
- unless语句
- case语句
5.2 Ruby中的条件
条件与真假值
之前介绍的比较运算符可以判断真假,作为if的条件使用。比较运算符的结果分别为true和false。除了比较运算符外,Ruby中还有很多其他可以作为条件判断的方法。例如,字符串的empty?方法。
p "".empty? #=> true
p "AAA".empty? #=> false
除了true和false外,还有其他值可以作为条件判断的值。例如,用正则表达式进行匹配时,匹配成功返回该字符串位置,匹配失败返回nil。
关于Ruby中的真假值的定义:
真:false,nil以外的所有对象。
假:false、nil
也就是说,Ruby会认为false与nil代表假,除此以外的所有值都代表真。另外,在 Ruby 中还有个约定俗成的规则,为了使程序更 容易理解,返回真假值的方法都要以 ? 结尾。建议大家在写程序时也遵守这个规则。
5.3逻辑运算符
在判断多个条件表达式时,我们会用到逻辑运算符&&和||.
条件1 && 条件2
表示条件1为真,并且条件2为真,整体的表达式返回真。两者同时为假,则整体的表达式返回假。
条件1 || 条件2
表示条件1为真,或者条件2 为真时,则整体的表达式返回真。两者同时为假,则整体的表达式返回假。
!条件
表示相反的条件。
在 Ruby 中,还有与 &&、||、! 意思相同,但优先级略低的逻辑运算符 and、or、not。
5.4 if语句
if 条件 then
处理
end
可以省略then
在这基础上可再加上elsif、else
if 条件1 then
处理1
elsif 条件2 then
处理2
elsif 条件3 then
处理3
else
处理4
end
可以省略then
5.5 unless语句
unless语句的用法刚好与if语句相反。unless语句用法如下:
unless 条件 then
处理
end
可以省略then
unless 语句的形式和 if 语句一样。但 if 语句是条件为真时执行处理,unless 语句则刚好相反,条件为假时执行处理。 下面是使用 unless 的例子(代码清单 5.3)。
a = 10
b = 20
unless a > b
p "a 不大于 b"
end
unless语句也可以使用else
unless 条件
处理1
else
处理2
end
这个与下面的if语句是等价的。
if 条件
处理2
else
处理1
end
对比以上两种写法,,我们可以知道处理 1 和处理 2 的位置互换了,if语句通过这样的互换,能达到与使用 unless 语句时同样的效果。
5.6 case语句
case 比较对象
when 值1 then
处理1
when 值2 then
处理2
when 值3 then
处理3
else
处理4
end
可以省略then
when可以一次指定多个值。
tags = ["A", "IMG", "PRE"]
tags.each do |tagname|
case tagname
when "P","A","I","B","BLOCKQUOTE"
puts "#{tagname} has child."
when "IMG", "BR"
puts "#{tagname} has no child."
else
puts "#{tagname} cannot be used."
end
end
执行示例:
ruby case.rb
A has child.
IMG has no child.
PRE cannot be used.
我们再来看看其他例子。
array = ["a", 1, nil]
array.each do |item|
case item
when String
puts "item is a String."
when Numeric
puts "item is a Numeric."
else
puts "item is something."
end
end
执行示例:
ruby case_class.rb
item is a String.
item is a Numeric.
item is something.
在本例中,程序判断传过来的对象类型是字符串(String 类)还是数值(Numeric 类),或者均不是以上两者,然后再输出相应的结果。 在这里,我们同样是使用 case 语句,不过判断的主体与之前的例子有点区别。
本例中的 when 实际并不是直接判断传过来的字符串,而是先查找该对象属于 哪个类,然后再根据这个类的信息来进行条件判断。
我们还可以根据正则表达式的匹配结果进行不同处理。下面是使用正则表达式做判断的 case 语句的例子。
text.each_line do |line|
case line
when /^From:/i
puts "发现寄件人信息"
when /^To:/i
puts "发现收件人信息"
when /^Subject:/i
puts "发现主题信息"
when /^$/
puts "头部解析完毕"
exit
else
##跳出处理
end
end
这是一个解析电子邮件头部的程序。为了简化程序,我们并没有考虑有多个头部的情况,而且电子邮件里的内容我们也没取出来。在这里,大家掌握程序的 大概的处理流程就可以了。
each_line 方法逐行读取电子邮件正文数据 text,并将每行的内容赋值给变量 line。
这个是处理文件、文本数据时的典型的写法。
接着 case 语句判断得到的字符串的内容,执行不同的处理。以 From: 开头时输出“发现寄信人信息”,以 To: 开头时输出“发现收信人信息”,以 Subject: 开 头时输出“发现主题信息”。
在正则表达式中,^ 表示匹配字符串的开始,$ 表示匹配字符串的结束。——译者注
=== 与 case
语句 在 case 语句中,when 判断值是否相等时,实际是使用 === 运算符来判断的。左边是数值或者字符串时,=== 与== 的意义是一样的,除此以外,=== 还可以与=~ 一样用来判断正则表达式是否匹配,或者判断右边的对象是否属于左边的类,等等。对比单纯的判断两边的值是否相等,=== 能表达更加 广义的“相等”。
p (/zz/ === "xyzzy") #=> true 判断正则表达式是否匹配
p (String === "xyzzy") #=> true 判断右边的对象是否属于左边的类
p ((1..3) === 2) #=> true
用 if 语句改写 case 语句的程序如下所示。请注意 when 指定的对象在=== 的左边。
5.7 if修饰符与unless修饰符
if 与 unless可以写在希望执行的代码后面。
puts "a 比b大" if a > b
这与下面的写法是等价的:
if a>b
puts "a比b大 "
end
5.8 总结
本章介绍了如下内容。
- 真假值
真假值是条件表达式的返回值。- nil或者false时为假。
- 除此以外的值为真。
- 条件判断语句
- if语句
- unless语句
- case语句
对象的同一性
所有的对象都有标识和值。
标识(ID)用来表示对象同一性。Ruby 中所有对象都是唯一的,对象的 ID 可以通过 object_id(或者 id)方法取得。
ary1 = []
ary2 = []
p ary1.object_id #=> 67653636
p ary2.object_id #=> 67650432
我们用 equal? 方法判断两个对象是否同一个对象(ID 是否相同)。
str1 = "foo"
str2 = str1
str3 = "f" + "o" + "o"
p str1.equal?(str2) #=> true
p str1.equal?(str3) #=> false
对象的“值”就是对象拥有的信息。例如,只要对象的字符串内容相等,Ruby 就会认为对象的值相等。Ruby 使用 == 来判断对象的值是否相等。
str1 = "foo"
str2 = "f" + "o" + "o"
p str1 == str2 #=> true
除了 == 以外,Ruby 还提供 eql? 方法用来判断对象的值是否相等。== 与 eql? 都是 Object 类定义的方法,大部分情况下它们的执行结果都是一样 的。但也有例外,数值类会重定义 eql? 方法,因此执行后有不一样结果。
p 1.0 == 1 #=> true
p 1.0.eql?(1) #=> false
凭直觉来讲,把 1.0 与 1 判断为相同的值会更加方便。在一般情况进行值的比较时使用 ==,但是在一些需要进行更严谨的比较的程序中,就需要用到 eql? 方法。例如,0 与 0.0 作为散列的键时,会判断为不同的键,这是由于散列对象内部的键比较使用了 eql? 方法来判断。
hash = { 0 => "0"}
p hash[0.0] #=> nil
p hash[0] #=> "0"