Ruby面試精選30題 - Day24 nil?, empty? 和, blank? present? 比較?

這一系列精選面試題寫下來,我發現新手工程師對於相似、接近的method或概念都會比較困惑,也難怪熱門面試要考這些題目了!這樣才能鑑別出面試候選人真的有弄懂程式觀念。也希望我整理好的這30篇鐵人賽文章,未來能幫助到許多想學Ruby、進而想找相關工作的新手們!


重點摘要:


Ruby經典面試題目 #24

  • nil?, empty?blank? present? 比較。
    What’s the difference between nil?, empty?blank? and present? `

1. nil?

在[Day21]的文章時,我們有討論到nil這個虛空的概念。而nil?是Ruby裡的方法,可以使用在任何物件,用來判斷該物件是否為nil,若nil為真,則傳回true

nil.nil?   # => true
false.nil? # => false
true.nil?  # => false
"".nil?    # => false
" ".nil?   # => false
[].nil?    # => false
{}.nil?    # => false

以上7行例子,我們可以發現,只有nil.nil?才會回傳true

2. empty?

empty?也是Ruby的方法,用來檢查集合Collection是否為空。(It returns true when the object’s length is zero.)

我們可以用empty?來測試包含:字串String陣列Array雜湊HashSet數組是否為空值。

" ".empty?   # => false **字串內有'空白鍵'的值,非空**

"".empty?    # => true 空字串
[].empty?    # => true 空陣列
{}.empty?    # => true 空雜湊

另外的集合例子:Set數組,是我新學到的Ruby概念:),指的是一組不重複的值是否為空值(a collection of unordered values with no duplicates)。(進一步說明請看Ruby API 文件)。

我們可以想像去餐廳裡點一個Set套餐,包含一主食、一甜點、一飲料,其中不會有任何重複的食物。在以下程式碼,記得要在第一行引入require 'set',不然會出現uninitialized constant Set (NameError)

require 'set'

s1 = Set[0, 'c', :s] #設定一個數組,包含數值、字元、符號
# => #<Set: {1, "c", :s}>
p s1.empty?  # => false, 此數組非空值

s2 = Set.new
p s2 #<Set: {}>
p s2.empty?  # => true, 此數組空空如也!

empty?就不像前面一開始提到的nil?可以作用在任何物件了。舉例來說,True,False,Nil這三個類別class,都不具有empty?方法:

p true.empty?  # => NoMethodError: undefined method `empty?' for true:TrueClass

p false.empty?  
 # => NoMethodError: undefined method `empty?' for true:TrueClass

p nil.empty?
# NoMethodError: undefined method `empty?' for nil:NilClass

此外,.empty?方法也不能使用在Enumerable列舉,原因是:我們無法確定傳入的參數迭代後,是否仍具有非nil的傳回值。 (Not every object which iterates and returns values knows if it has any value to return. [原文])。

好家在!我在[第20天]曾經有花點時間研究Enumerable列舉方法的各種可能,當不能確定元素內值的完整資訊的情況(例如:搜尋不到自己要的字元、字串等)其實還蠻常見的。[再複習一下Ruby API : Enumerable]

由今天的例子,我明白到一個道理:使用一個工具(method)之前,要明白它的管轄範圍(隸屬於哪個class的method),不然就好像提油救火一樣不合時宜唷!

3. blank?

既然empty?有這麼多使用限制,而可以使用在所有物件的的nil?又只能確認nil時為true,有沒有個各取兩者優勢的好方法呢?

將將將!終於來到我第一個研究Ruby on Rails的方法:blank?。我們都知道Rails是基於Ruby寫出的框架,所以想必Rails整合許多Ruby的功能,讓寫出網站的動態功能變成更簡潔的事情。

blank?()就是一個結合我們在前面提到的前兩組方法 nil?empty?(這也是我第一次認真點開Rails文件Rails API: blank?()研究~~怎麼有點興奮的港結!!!)

來看看rails在Github上的程式細節,了解它是怎麼改寫的:

# File activesupport/lib/active_support/core_ext/object/blank.rb, line 19

def blank?
  respond_to?(:empty?) ? !!empty? : !self #是empty或者self是nil,回傳true
end

因此,address.empty? || !address

可以寫成:address.blank?

blank?()為真的情形

Rails API: blank?()裡面提到:

An object is blank if it’s false, empty, or a whitespace string.

  • nilfalse:是falsy
  • ""是空字串
  • " "是空白鍵
  • []是空陣列
  • {}是空雜湊

They are all blank.

以Rails程式碼表達如下:

[ nil, false,  "", " ", [], {} ].all?(&:blank?) # => true

我相信大家一定都能理解在製作動態功能網站時類似申請使用者帳號密碼的場景,密碼字元不能是nilempty。或安插空白鍵。這在rails裡可以直接整合成blank?()功能喔(真是太方便了!)

4. present?

present?blank?就像一對愛唱反調的兄弟一樣,做的剛好是完全相反的事情(An object is present if it’s not blank. [Rails API)]

# File activesupport/lib/active_support/core_ext/object/blank.rb, line 26
def present?
  !blank?
end

present?從字面上的意思確認是否存在(非nil且非空值且非空白鍵),若存在,則回傳True。present?也是專屬Rails的method。

present? is also an ActiveSupport extension to Ruby Object and it is the negation of blank?. 原文

以Rails程式碼表達如下:

[ nil, false,  "", " ", [], {} ].any?(&:present?) # => false

我發現到自己在鐵人賽第10天之後,只要新學到任何Ruby工具(method),下意識就會馬上去查Ruby Doc看它們屬於哪個類別、以及將Ruby Doc的例子改寫為自己的使用案例…這真是巨大的成長與蛻變!(給自己拍拍手~~)這或許是更有意識地去學習一套新東西的去強迫自己成長的附加價值吧!:)

最後,附上超級比一比統整表格:

nil? empty? blank? present?
Ruby Ruby Rails Rails
若物件為nil,則回傳true 集合(String, Array…etc)的長度為0,則回傳true nilempty空白鍵,則回傳true 若此物件存在(非nil且非empty),則回傳true

Ref: