2017-02-16 54 views
2

的碼本部分計算每個算術系列直到幷包括數用戶放入的值:關於注射方法:它是如何工作的?

print "enter a number: " 
num = gets.to_i 
(1..num).inject(0) do |res, e| 
    res += e 
    p res 
end 

我認爲(1..num)是的範圍內,num作爲用戶輸入。我知道inject通過應用由命名方法或運算符的塊或符號指定的二進制操作來組合枚舉的所有元素。

我不明白這行的每個元素的作用:

(1..num).inject(0) do |res, e| 
  • 是什麼|res, e|意思?它必須是定義什麼inject的塊,但是例如rese代表什麼? (e大概是要素?)
  • 是什麼(0)立場?
  • 指令do做什麼?
  • 什麼是它關於(1..num)inject(0)連接?
  • 我是正確的假設,p末剛剛代表putsprint
+0

您可以組合塊的兩行:'p res + e' – Stefan

回答

5

inject取一個可選的起始值,一個塊取中間值和元素並返回一個新的中間值。

所以:

是什麼(0)代表什麼?

起始值參數爲inject

什麼命令 「不」 嗎?

它不是一個命令;它標誌着塊的開始(由end終止)。 .inject(0) do ... end幾乎(除了一些語法問題)與.inject(0) { ... }相同。通常,do ... end用於多行塊,{ ... }用於單行塊,但這不是一個規則。

是什麼|資源,E |意思?

這些是塊參數(中間值和當前元素),這裏可能分別在「result」和「element」之後調用。

讓我們來看一個簡化的例子:(1..3).inject(0) do |res, e| res + e end將設置中間結果爲0。然後它會通過這個中間結果並且注入第一個可枚舉元素:res0e1。該塊的值是其最後一個表達式的值,即1(結果爲0 + 1)。現在這個1成爲新的中間值,並且2成爲下一個當前元素。該塊的值爲3(結果爲1 + 2)。在下一次迭代中,中間值是3,當前元素也是3,導致63 + 3)。現在我們達到了上限,範圍將停止產生元素,inject返回計算的最後中間結果6

另外,最後一個問題我是否正確地認爲最後的「p」只代表放入或打印?

差不多。 p是它自己的野獸。 p x大致與puts x.inspect; x同義 - 即它以不同的格式打印該值,而不像puts總是返回nil,p返回該值不變。因此,p res在您的塊結束時不會通過使其返回nil而銷燬代碼,但會透明地返回res

3

inject是一種將集合(例如數組或範圍)簡化爲單個值的方法。它通過爲集合中的每個元素執行一次塊來完成此操作。該塊有兩個參數:正在處理的當前值以及最終將返回的單個值。 inject本身需要一個參數(除了塊),這是它的初始值。

以此爲例。

x = [1, 2, 3, 4, 5].inject(0) do |result, current| 
    result + current 
end 

我們有一個數字列表,[1, 2, 3, 4, 5]。我們將它們歸結爲一個單一的數字。

我們從0開始,因爲那是inject的論點。這意味着塊首次運行時,result將爲0.

因此塊首次運行。 result是0,current是1,第一個元素。我們說result + current(這是1)。這是塊內的最後一個表達式,所以它就是該塊返回的內容。

在該塊的末尾,inject表示「好的,我們有更多元素在集合中嗎?」是啊。所以塊再次運行。 這一次是,result是返回的最後一個數據塊,它是1,current是第二個元素2

該塊運行,並以result + current或1 + 2結束,即3。還剩下元素,所以我們再次運行。這一次,result爲3,current爲3. result + current,6。還有更多值要走,下一次運行result爲6,current爲4. 6 + 4 = 10.還有更多值要去,下一次運行result是10,current是5. 10 + 5 = 15.

然後塊完成,並且沒有剩餘元素了。所以inject本身返回最終值,15.所以最後,x = 15。我們通過添加東西將我們的列表歸結爲一個數字。

res在您的示例中代表結果,而e代表元素。你可以稱他們任何你想要的。您可以在添加時將它們稱爲sum,或者如果相乘,則可以將它們稱爲product。但他們不一定是數字。您可以使用inject來沸騰字符串數組,字符範圍,數組數組,無論您想要的集合。該塊只是告訴它如何。

1

興奮地看到你正在學習Ruby,歡迎!

在您的專業水平最好的書籍學習。

一些快速的答案

  • 1..num是一個範圍對象
  • .inject(0) do ... end是一個帶有TWO參數的方法調用,值0和代碼塊
  • do |a, b| ... end是一個有兩個參數
  • rese一個代碼塊是非常糟糕的變量名,也許更好的使用sumeach
  • p是打印調試信息的全局方法,類似於puts但不相同

希望幫助疏通你。

相關問題