iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 3
0
自我挑戰組

Ruby and Rails 的二三事系列 第 3

Ruby and Rails 的二三事 - Day03 Array and Hash

  • 分享至 

  • xImage
  •  

好啦,昨天介紹完變數和常數,今天就從 Array 和 Hash 繼續下去吧!!

什麼?你說我還沒講資料型別?阿是不會自己去google 喔?

別急別急,讓我們慢慢看下去...


Array

首先讓我們來看看下面這些陣列(Array):

 a = ['What', 'I said is', 'is rubbish', 'everyone here']
 
 b = [1, 2, 3]
 
 c = [true, true, true, true, false]
 
 d = ['懦夫救星', 28825252, true ]

嗯?好像有奇怪的東西混進程式碼裡面...暫時先不管他啦!

上面的 a, b, c, d 都是陣列,在Ruby 的世界,陣列裡面要放什麼,隨你高興。
你要都放字串,數字,或是boolean值,或是混在一起做成撒尿牛丸?,歡喜就好。

在Ruby 的世界裡,幾乎所有的東西都是物件,依照物件類別的不同,
會有不同的方法可以使用。

比如說:

  • length, 可以幫我們取得陣列的長度(陣列元素的個數)
a = ['What', 'I said is', 'is rubbish', 'everyone here']

a.length
=> 4
  • array[index], 可以讓我們直接取得陣列中的元素(index 是從0 開始計算的)
a[0]
=> "What"
a[3]
=> "everyone here"
a[-1]
=> "everyone here"
a[-4]
=> "What"
a[-5]
=> nil

相信眼尖的你應該有發現,沒錯:

在Ruby 的世界裡index 可以是負數,會自動幫你從最後一個元素倒著數。

  • reverse, 可以反轉陣列內元素的順序
a.reverse
=>["everyone here", "is rubbish", "I said is", "What"]

更多Array可以使用的方法

還記得昨天提到的 each 嗎? 他其實是Array可以使用的方法之一;
下面我們就來進一步介紹幾個比較常用的方法:

  • select
  • map
  • reduce

Select - 選出陣列中滿足特定條件的元素,回傳一個新的陣列

首先,來試著選出 陣列a 中所有的奇數。
就用昨天剛學會的 each 來試試看吧!
寫起來大概會像這樣:

a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

b = []

a.each do |i|
 b << i if i % 2 == 1
end

p b  # [1, 3, 5, 7, 9]

如果改用select來寫呢?

a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

p a.select {|i| i % 2 == 1} # [1, 3, 5, 7, 9]

WTF?!!! 不不不,這是Ruby的日常喔!
稍微觀察一下,可以看出select的用法是這樣的:

array.select{|i| "篩選的條件"}

map - 對陣列中的元素做處理,然後回傳一個新的陣列

接著我們試著將 陣列[1, 2, 3, 4, 5] 變成 [2, 4, 6, 8, 10]。
一樣,先用 each 來做,寫起來會像是這樣:

c = [1, 2, 3, 4, 5]

d = []
c.each do |i|
  d <<  i * 2
end

p d # [2, 4, 6, 8, 10]

那如果改用map寫呢?

c = [1, 2, 3, 4, 5]
p c.map{|i| i * 2} # [2, 4, 6, 8, 10]

WTF? 沒有剛剛那麼驚訝了吧?
聰明如你應該已經發現了:

如果你需要再迴圈外面定義一個變數,然後在迴圈裡面重複的取用他;
那在Ruby通常會有更簡單的寫法。

reduce - 對陣列中所有的元素,依據設定的條件,進行二元運算

接著,我試著來計算1到10的總和吧!
老樣子,我們先用each來做:

  total = 0
 [*1..10].each do |i|
   sum = sum + i
 end
 
 p sum # 55

看出端倪了嗎?換成reduce的話,可以寫成這樣:

 p [*1..10].reduce(0) {|total,i| total + i} # 55

有看到奇怪的東西嗎?

[*1..10 ] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

*是建立Array的一種縮寫

此外還有一個需要注意的地方:

reduce(0) ,括號裡面的 0 ,是我們給total設定的初始值,它的作用和用each的寫法時,
在外面寫的 total = 0 一樣。

 p [*1..10].reduce {|total,i| total + i} # 55

當你沒有設定初始值, reduce方法,會自己拿第一個元素作為初始值,在這個例子裡就是 1 。

可以透過下面的程式碼觀察兩者的差異:

[*1..10].reduce(0){|total,i| p (total + i) } # 1, 3, ... 45, 55
[*1..10].reduce{|total,i| p (total + i) } # 3, ... 45, 55

Hash

公堂之上假設一下,我想是無傷大雅的
假設我們有一籃水果,裡面有蘋果5個,香蕉3個,芒果4個。
下面三種寫法的意思都是一樣的:

basket = { "apple" => 5, "banana" => 3, "mango" => 4 }
basket = { :apple => 5, :banana => 3, :mango => 4 }
basket = { apple: 5, banana: 3, mango: 4 }

在 basket 這個 hash 當中:
"apple"、"banana" 和 "mango",我們稱之為key
5、3和4,我們稱之為value

但是,當你想知道蘋果有幾個的時候:

basket[:apple] #只有這樣才拿得到值
=> 5          

這裡的 :apple 他是一個符號(symbol)

each 也是 Hash 可以使用的方法之一喔!
所以我們可以這樣做:

basket.each { |i|  p i }

#印出
# ["apple", 5]
# ["banana", 3]
# ["mango", 4]

你也可以像下面這樣

basket.each {|k,v| p "Key is #{k}, Value is #{v}"}
#印出
#"Key is apple, Value is 5"
#"Key is banana, Value is 3"
#"Key is mango, Value is 4"

或者,你也可以用 keys 和 values 的方法,只取出其中一項:

basket.keys
 => ["apple", "banana", "mango"]
basket.values
 => [5, 3, 4]

好,今天的鐵人賽就到這邊告一個段落,明天見!


上一篇
Ruby and Rails 的二三事 - Day02 流程控制、迴圈與迭代
下一篇
Ruby and Rails 的二三事 Day04 Symbol (符號)和 String(字串) 的差別
系列文
Ruby and Rails 的二三事19
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言