2010-03-22 11 views
9

我創建一個Rails應用程序,並使用該代碼在我的一個方法爲什麼我需要使用.inject(0)而不是.inject來完成這項工作?

item_numbers.inject(0) {|sum, i| sum + i.amount} 

ITEM_NUMBERS是從我ITEM_NUMBERS表對象的數組。我應用於它們的.amount方法在單獨的表中查找item_number的值,並將其作爲BigDecimal對象返回。顯然,注入方法然後添加所有返回的i.amount對象,這工作得很好。

我只是好奇,爲什麼當我寫這篇聲明的

item_numbers.inject {|sum, i| sum + i.amount} 

據我信賴的鶴嘴鋤,這些書應該相當於沒有工作。是否因爲i.amount是BigDecimal?如果是這樣,爲什麼它現在工作?如果不是,那爲什麼它不起作用。

回答

14

我們可以在API閱讀:

如果你沒有明確指定的 備忘錄的初始值,然後使用 集合的第一個元素用作 備忘錄的初始值。

因此item_numbers [0]將被指定爲初始值 - 但它不是一個數字,它是一個對象。所以我們得到一個錯誤

未定義的方法'+'。

因此,我們必須指定初始值爲0

item_numbers.inject(0){|總之,我| sum + i}

+0

您可以做一點測試 (10..15).inject do | sum,i | p總和 總和+ I 端 它將返回: 10,第21,33,46,60 => 75 正如你可以看到_sum_會從陣列的第一項作爲初始值 – fl00r 2010-03-22 12:05:24

+0

這解釋了它很好。謝謝。 – brad 2010-03-22 12:06:09

7

這是因爲您正在訪問i.amount而不僅僅是簡單的i。在不起作用的版本中,您隱式執行item_numbers[0] + item_numbers[1].amount + ...

其中一種簡寫爲item_numbers.map(&:amount).inject(&:+),但如果map未返回枚舉數,則這種方式可能導致在列表上進行兩次迭代。

如果沒有說服你,看看被打印出來,如果我們定義在一個長整數方法amount在返回之前打印值:

irb(main):002:1> def amount 
irb(main):003:2>  puts "My amount is: #{self}" 
irb(main):004:2>  return self 
irb(main):005:2> end 
irb(main):006:1> end 
=> nil 
irb(main):007:0> [1,2,3].inject { |sum, i| sum + i.amount } 
My amount is: 2 
My amount is: 3 
=> 6 
irb(main):008:0> [1,2,3].inject(0) { |sum, i| sum + i.amount } 
My amount is: 1 
My amount is: 2 
My amount is: 3 
=> 6 
irb(main):009:0> 

我們可以清楚地看到amount不叫第一個元素上時,初始值沒有顯式地傳入

+0

+1爲清楚的例子說明了完美的行爲 – Jean 2010-03-22 12:52:08

相關問題