2016-04-09 11 views
0

#injectの中にwhileループを使用しようとしています。しかし、最後のメモはある時点では無くなり、なぜ私は理解できません。#injectのメモはどのように機能しますか?

class TestClass 
    BASE_ARRAY = [5, 1] 

    def test_method(value) 
    result = [] 

    BASE_ARRAY.each do |item| 
     while item <= value 
     result << item 
     value -= item 
     end 
    end 

    result 
    end 

    def test_method_alternate(value) 
    BASE_ARRAY.inject do |memo, item| 
     while item <= value 
     p memo 
     # memo << item (if left, returns NoMethodError for nil Class) 
     value -= item 
     end 
    end 
    end 
end 

solution_one = TestClass.new.test_method(11) 
p solution_one # => [5, 5, 1] 

solution_two = TestClass.new.test_method_alternate(11) 
p solution_two 
# => [] 
    [] 
    nil 

どのようにアキュムレータがnilになるん:ここに私の例である(私はちょうど期待される結果を表示する例を#eachを使用しますか)?

答えて

1

をあなたはwhile loopから最初にnilを取得している:

結果値を供給するためにbreakが使用されない限り、whileループのループはnilです。結果

は、チェーン内の他のステートメントの結果次のようになります。

while 
-> do |memo, item| 
    -> BASE_ARRAY.inject 
    -> test_method_alternate(11) 
     -> solution_two 

配列を埋める.inject持ってするには、最初として使用する空の配列を提供することをお勧めしますmemo:次に

​​

、アレイは、ブロックの結果であることを確認すること:

... do |memo, item| 
    while item <= value 
    memo << item 
    value -= item 
    end 
    memo # <--- 
end 
+0

ありがとう、@ジョナサン! 'while'の戻り値に関する'解説 'は、私がしなければならなかった'メモ 'を返すだけでなく、助けになりました。ありがとう! – user3097405

1

2つのこと:

  • あなたが値をmemoを初期化する必要があるが、この場合には、あなたは[]をお勧めします。
  • injectの各繰り返しでmemoを返す必要があります。

だから、あなたはこのようなことにあなたの方法を変更することにより、[5, 5, 1]のあなたの望ましい結果を得る必要があります。

def test_method_alternate(value) 
    BASE_ARRAY.inject([]) do |memo, item| 
    while item <= value 
     memo << item 
     value -= item 
    end 
    memo 
    end 
end 
+0

ありがとう@paul!私が質問をタイプしたときに、メモの値が「[]」でないことは間違いでしたが、私はメモを返さず、それが問題でした。ご協力いただきありがとうございます! – user3097405

関連する問題