2010-07-24 67 views
7

我是Ruby的新手,我注入方法有一個奇怪的問題。使用Ruby注入時沒有類

當我這樣做:

(1..10).inject(0) {|count,x| count + 1} 

結果是10,符合市場預期。但是,當我做

(1..10).inject(0) {|count,x| count + 1 if (x%2 == 0)} 

我得到一個錯誤:

NoMethodError: undefined method `+' for nil:NilClass 
    from (irb):43 
    from (irb):43:in `inject' 
    from (irb):43:in `each' 
    from (irb):43:in `inject' 
    from (irb):43 

我真的不明白爲什麼(大概)數在第二個例子中爲零,但不是第一個。無論如何,我將如何計算從1到10使用注入的平衡?

回答

14

表達式count + 1 if (x%2 == 0)返回nil當條件不成立時,count被設置爲因爲這是注入方法的本質。

你可以通過返回count + 1當它是偶數修復它,只是count時,它不是:

(1..10).inject(0) { |count,x| x % 2 == 0 ? count + 1 : count } 

一個完全不同的解決方案是使用select選擇偶數和使用Array#length方法來算他們。

(1..10).select { |x| x % 2 == 0 }.length 
+1

如果你使用Ruby 1.8.7+,您還可以使用可枚舉#計數,即'(1..10).Count之間(:偶)' – 2010-07-24 02:56:18

+0

如何可愛! - – 2010-07-24 03:19:49

+0

謝謝!這現在非常合理。就效率而言,注入方式更好,因爲它不會導致建立額外的數組。在這個例子中,這並不重要,但是如果我們從更大的範圍中選擇1000個值,該怎麼辦? – 2010-07-25 16:30:21

3

yjerem正如已經指出的,將count + 1 if (x%2 == 0)進行評估,以nil當x爲奇數。並且,這裏是問題:nil值將被分配給count,所以下一次迭代將是nil + 1,這會導致報告的錯誤。

瞭解如何注入作品(從ruby-doc複印件)

enum.inject(initial) {| memo, obj | block } => obj

enum.inject {| memo, obj | block } => obj

Combines the elements of enum by applying the block to an accumulator value (memo) and each element in turn. At each step, memo is set to the value returned by the block. The first form lets you supply an initial value for memo. The second form uses the first element of the collection as a the initial value (and skips that element while iterating).

的規則將讓你遠離這種錯誤是很重要的:塊應始終返回同一類型的值作爲的累加器。如果你的例子,該塊將返回nil類型的時候x%2==0如果false

(1..10).inject(0) {|count,x| count + 1 if (x%2 == 0)}