第5章 条件判断

本章主要讲述三个内容:

  • 什么是条件判断
  • 条件判断中第比较运算符、真假值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 指定的对象在=== 的左边。


截屏2021-01-29 下午2.05.38.png

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"
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,319评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,801评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,567评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,156评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,019评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,090评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,500评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,192评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,474评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,566评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,338评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,212评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,572评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,890评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,169评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,478评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,661评论 2 335

推荐阅读更多精彩内容