Day14 - Ruby比一比:#each #map和#collect method

今天要講的是迭代器(iterator)。什麼是迭代器呢?它的好處就是會一個一個地傳回集合裏的元素,讓咱們能夠利用迭代方法作重複的事。面試

 

在Ruby裏的collection集合裏有Array數組和Hash哈希。數組

 

今天要介紹三種用在collection集合的迭代器分別叫each,map和collect,這也是常見的Ruby面試考題呢!.net

 

Ruby經典面試題目#14索引

Day14 each,map和collect比較?What's the difference between each,map and collect?element

 

咱們來使用這三種迭代器,在Array和Hash兩種集合中各舉幾個生活化的例子,相信你們就比較容易暸解囉!get

 

Arrayhash

Array#eachit

最近我在進行旅行存錢計劃。我有三個銀行賬戶,NAB,CAN,和WESTPAC,開戶金額分別爲100,200,300。因此我寫一個數組集合放入初始金額[100,200,300]。io

 

假設我打算開始從本週開始在每一個賬戶存入50元(+50),能夠在數組後加上.each方法:進階

 

[100,200,300].each {|n| puts n+50}

結果列出各個賬戶的金額(注意:puts寫在block大括號裏):

 

150

250

350

通過.each方法做用以後,只會分別印出同一數組中各個元素的值,不會產生新數組。

 

Array#collect

以上案例,換成.collect試試看:(注意!puts寫在前面)

 

puts [100,200,300].collect {|n| n+50}

.collect會幫咱們把結果放入新的數組。結果印出(xujiaqing):

 

[150,250,350]

Array#map

一樣的,.map方法也會幫咱們產生新的數組。

 

puts [100,200,300].map {|n| n+50}

結果印出:

 

[150,250,350]

那.collect與.map又有什麼不一樣?以及分別用在什麼狀況呢?這時候就要翻查Ruby手冊裏,關於.collect和.map的介紹了:

 

collect { |item| block }→new_ary Invokes the given block once for each element of self.Creates a new array containing the values returned by the block.

 

hmm…好像看不出有什麼差別呢!

 

map { |obj| block }→array Returns a new array with the results of running block once for every element in enum.

 

近一步查詢stackoverflow,果真有其餘網友問過相似的問題。咱們能夠把.map看成是.collect的別名(map is an alias for collect),實務上比較常使用.map喔!

 

更多Array#map用法

如今把個人銀行賬戶數組存進account變數裏,再用.inspect檢查數組的值:

 

account = [100,200,300]

account.map {|n| n+50}

p account.inspect

結果印出

 

「[100,200,300]」

若是在.map後加上驚歎號.map!呢?

 

account.map!{|n| n+50}

p account.inspect

存進去本來的數組了。錢錢變多了!開心~~(加上!驚歎號的方法,一般表明當心!注意!的意思)

 

在這裏的.map方法會讓本來的物件數組被改變呢!

 

「[150,250,350]」

Hash

Hash哈希是一對key與value的集合。在剛剛的銀行賬戶例子裏,咱們能夠把銀行名稱看成索引,存款數目看成值:

 

account = {「NAB」=> 100,「CAN」=> 200,「WEST」=> 300}

利用哈希來展示目前的信息(賬戶名稱、存款金額),這樣就可讀性更加清楚了。

 

Hash#each

如今我想要計算三個賬戶加總共有多少錢,以.each的方式可寫爲:

 

mymoney = 0

account.each {|bankname,saving| mymoney += saving} #把索引和值列出

print「My Money: $」+ mymoney.to_s

或是

 

mymoney = 0 #設定初始值

account.each{|bank| mymoney += bank[1]} #依序加總bank集合裏第二個元素bank[1]

print「My Money: $」+ mymoney.to_s

結果都會印出:

 

My Money: $ 600

Hash#map

在Hash裏,把.each換成.map或是.collect:

 

mymoney = 0 #設定初始值

account.collect{|bank| mymoney += bank[1]} #依序加總bank集合裏第二個元素bank[1]

print「My Money: $」+ mymoney.to_s

結果都是同樣的:

 

My Money: $ 600

Hash#map結合Array#each與Array#map

如今要進階到一個較爲複雜的例子:hash裏包含索引和值兩部份,那咱們可不能夠把數組看成一種值,放在裏面呢?

 

固然能夠!

 

假設個人NAB銀行下有2個子賬戶,CAN銀行下有3個子賬戶,分別放入這些資產:

 

hash = {「NAB」=> [「Cash」,「Gold」],「CAN」=> [「Bitcoin」,「Litecoin」,「Ethereum」] }

利用hash.map會產生一個新的數組:(進一步瞭解說明,看stackoverflow的說明)

 

p hash.map {|n| n}

結果顯示:

 

[[「NAB」,[「Cash」,「Gold」]],[「CAN」,[「Bitcoin」,「Litecoin」,「Ethereum」]]] #我有好多賬戶!NAB下有2個,CAN下有3個

我想分別提取出銀行:賬戶名稱的這一對信息,而且用逗號.join(「,」)隔開。

 

爲了程序可讀性,hash的索引命名爲bank(銀行名),值爲account_arry(放了不一樣數目的子賬戶數組)。在走account_arry.each展開數組迭代器時,每在集合裏走完一個元素,就印出#{bank}:#{sub_account}

 

p hash.map {

|bank,account_arry| account_arry.each{

|sub_account|「#{bank}:#{sub_account}」}

}.join(「,」)

結果僅印出:

 

「Cash,Gold,Bitcoin,Litecoin,Ethereum」

奇怪,這不是我要的結果呀!我很但願賬戶前面能顯示出銀行名稱呢!

 

這是由於剛剛說過,arry.each會回傳數組自己,在這個例子裏,分別回傳的是[「Cash」,「Gold」]和[「Bitcoin」,「Litecoin」,「Ethereum」]

 

改爲.map試試看:

 

p hash.map {

|bank,account_arry| account_arry.map{

|sub_account|「#{bank}:#{sub_account}」}

}.join(「,」)

結果顯示爲:

 

「NAB: Cash,NAB: Gold,CAN: Bitcoin,CAN: Litecoin,CAN: Ethereum」

這是由於account_arry.map自動幫咱們產生新的數組,放進bank與對應的sub_account並回傳。

 

最後放個小小的比一比表格做爲總結(expatvision):

 

each map / collect

Array方法Enumerable(列舉)方法

回傳Array自己產生新的Array並回傳

祝福你們能順利collect不一樣的資產,不論是有形的財富、仍是無形的知識,最後均可以達成錢多多的心願喔!:D

相關文章
相關標籤/搜索