Ruby面試精選30題 - Day23 Ruby的'==','===' 'eql?' 'equal?'
前幾天我們把焦點集中在True or False(判斷真假),今天來研究幾個比較是否相等的方法!在程式世界裡,真假與相等都有更多元、更超乎想像的概念。如果是程式新手,可能會對這幾個看起來特別像的運算子:==, ===, eql?, equal?充滿黑人問號…???
趕快來看看今天的題目!
重點摘要:
Ruby經典面試題目 #23
- 解釋Ruby裡的
==,===,eql?,equal。 Explain each of the following operators ==, ===, eql?, equal?`
有些方法比其他的方法更相等(Some are more equal than others)。這是怎麼回事?讓我們繼續看下去~
1. ==
== 檢查兩個運算子的值是否相等 (check if the value of two operands are equal)
2. eql?
如果接收器和參數的值和類型都相等,則為true. ( checks if the value and type of two operands are the same ),
eql?與 == 比較
來比較一下==和.eql?的用法:
100 == 100.0 #=> true
100.eql?(100.0) #=> false
從以上例子看到100與100.0同樣皆為數值1,但1的類型為Fixnum,1.0的類型為Float浮點數(包含小數點)。
3. ===
=== 測試case語法中、when子句內的相等性 (test equality within the when clause of a case statement)
舉個生活化的例子來描述case語法:
下週我要出遠門旅行,因此我規劃去超市裡購物,在旅行大背包裡放一些食物補給品。我想要以[第7天]學到的符號Symbol將food歸類:
def type_of(food)
case food
when 'Apple'
:fruit
when 'Banana'
:fruit
when 'Chocolate'
:sweet
when 'Noodles'
:meal
when 'Chips'
:junkfood
else
:unknown
end
end
p type_of 'Chips' # => :junkfood
hmmm….被發現買洋芋片是垃圾食物了了!
=== 與 if else
===代表的是 case equality
以上的case...when,其實是從if...else加上===的語法改寫而來。
def type_of(food)
if 'apple' === food
:fruit
elsif 'Chocolate' === food
:sweet
elsif 'Noodles' === food
:meal
elsif 'Chips' === food
:junkfood
else
:unknown
end
p type_of 'Nuts' # => :unknown
旅行時買一些腰果核桃補充能量,比洋芋片建康一些。XD
補充一下:Ruby的when後面可以放多個參數,讓程式更簡潔,因此我來放更多的食物Orange和Bread進去旅行大背包:
def type_of(food)
case food
when 'Apple', 'Banana', 'Orange'
:fruit
when 'Chocolate'
:sweet
when 'Noodles', 'Bread'
:meal
when 'Chips'
:junkfood
else
:unknown
end
end
p type_of 'Orange' # => :fruit
=== 不是 ==
從以上大背包放食物的例子我們可以發現,===比的是case equality in case statement(更近一步來說,比的是上層的類別物件class object),所以以下四條判斷式,會顯示為全部為真:
p Class === Class
p Object === Object
p Class === Object
p Object === Class
# all true. 萬物皆為物件!
比較tricky的部分是Fixnum,我發現到了如果將Fixnum擺在===(threequality)的右邊,結果為假:
p 1 === 1 # => true
p Fixnum === 1 # => true
p 1 === Fixnum # => false
p Fixnum === Fixnum # => false
#warning: constant ::Fixnum is deprecated
Ruby Gotchas這份slide説明:
A better name (IMHO, 以我的觀點來說) might be
.describes?, or overload.includes?
這或許就是為什麼我們不能把拿來比較的參數放在左邊,而是右邊:)
===, == 與 Regular Expression
使用===的好處就是可以用正規表示式提取、比較更多符合我們需求的條件。從以上的結論我們發現要將正規表示式放左邊。參考Ruby Doc 關於Regexp方法下的Public Instance Methods這頁說明,我們可以分別用 ===和 == 了解各項舉例是否為真:
p /banana/ === 'banana' # => true
p /banana/ === /banana/ # => false
p /banana/ == 'banana' # => false
p /banana/ == /banana/ # => true
為何在上述banana的例子裡,/banana/ === 'banana'為真,而
/banana/ == 'banana' 為假呢?
Regexp#===是用來比對(match)字串是否包含/正規表示式/裡的字符號 (tests whether or not the argument matches the regular expression.)。而在此例子裡,'banana'字串的確包含banana這些字符號。
但/banana/和'banana'本身並不是同一個值,所以==結果為假。
4. equal?
equal? : 如果接收器和參數的物件id(記憶體位置)相同,則為true (compares if both operands refer to the same object i.e. have the same object id)
equal? 與 eql? 與 == 比較
最後我們來用Ruby is Awesome作為總結吧!
ruby = "awesome"
rails = "awesome"
p ruby == rails # => true #ruby和rails都很awesome!
p ruby.eql? rails # => true
# ruby和rails不但都很awesome, 而且兩者的類型都是字串(string)!
p ruby.equal? rails # => false
#ruby和rails分別存在不同的記憶體位置,它們不是同一個物件
p ruby.object_id #70263932897220
p rails.object_id #70263932897160
超級比一比:
| == (等於) | === | eql? | equal? |
|---|---|---|---|
| 檢查兩個運算子的值是否相等 | 測試case語法中的when子句相等性 (object class) |
如果接收器和參數的值和類型都相等,則為true |
如果接收器和參數的object id相同,則為true |
Ref:
- Ruby Interview Questions - Quizbucket
- Ruby Doc: rxp === str → true or false
- Ruby算數運算符
- Ruby Gotchas
- === vs. == in Ruby
- What does the “===” operator do in Ruby?
- How A Ruby Case Statement Works And What You Can Do With It
- The Power of Ruby’s Case Statement
- The Elements of Style in Ruby #7: The Case Against ===