2017-02-20 46 views
0

我對此代碼的期望是數字3.爲什麼這不起作用?在混合陣列中添加數字

mixed_array=[1,'cat',2] 
    mixed_array.inject(0) do |memo,num| 
    memo += num if num.is_a?Integer 
    end 

NoMethodError: undefined method `+' for nil:NilClass 

回答

1

你幾乎有:

mixed_array.inject(0) do |memo, num| 
    next memo unless num.is_a?(Integer) 
    memo + num 
end 
#=> 3 

使你的代碼工作:

mixed_array.inject(0) do |memo, num| 
    memo += num if num.is_a?(Integer) 
    memo # return memo on each iteration, because it becomes nil with non-integer element 
end 
#=> 3 
0

你有什麼不工作,因爲:

  1. memo += num if num.is_a?Integer值當時是不是Integer
  2. 將每個塊的值作爲memo送入下一次迭代。

你的塊計算爲nil在第二次迭代所以你最終將會嘗試評估:

nil += 2 if 2.is_a? Integer 

,並有你NoMethodError。

你可能更好做這兩個步驟清晰:

mixed_array.select { |e| e.is_a? Integer }.inject(:+) 

,或者甚至較爲寬鬆的版本:

mixed_array.select { |e| e.is_a? Numeric }.inject(:+) 

或使用Ruby的新版本:

mixed_array.select { |e| e.is_a? Numeric }.sum 

如果你沒有教條主義反對三元論,那麼你也可以這樣說:

mixed_array.inject(0) { |memo, num| memo + (num.is_a?(Integer) ? num : 0) } 
mixed_array.sum { |e| e.is_a?(Integer) ? e : 0 } 

如果您知道的mixed_array非數字元素是字符串看起來不像數字或以數字開頭(即沒有像'0''11 pancakes',...),那麼你可以說:

mixed_array.map(&:to_i).inject(:+) 
mixed_array.inject(0) { |memo, num| memo + num.to_i } 
... 

但是這可能使太多的假設。

0

你可以,如果你認爲它是一個兩個階段的操作,而不是一個很多更容易做到這一點:

mixed_array=[1,'cat',2] 

mixed_array.grep(Integer).inject(0, :+) 
# => 3 

過濾掉來自陣列的所有非整數元素,共同增加了休息。

請記住,inject將上次迭代的返回值作爲下一個的種子。您的if條款必須返回一個備用值。你結束了這個,如果你解決它:

memo += num.is_a?(Integer) ? num : 0 

你也可以去同一個足夠好的解決方案,如:

memo += num.to_i 

取決於你試圖屏幕什麼樣的數據出。

0
mixed_array = [1, 'cat', 2, [3, 4], :a, { b: 5, c: 6 }, 7] 

mixed_array.reduce(0) { |tot, obj| tot += Integer(obj) rescue 0 } 
    #=> 10 

當陣列可以包括一個或多個浮標,並要返回浮點:

mixed_array = [1, 'cat', 2, [3, 4], :a, { b: 5, c: 6 }, 7, 8.123] 

mixed_array.reduce(0) { |tot, obj| tot += Float(obj) rescue 0 } 
    #=> 18.122999999999998 

Kernel::IntegerKernel::Float