11

Rails アプリを作成しており、メソッドの 1 つでこのコードを使用しています

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

item_numbers は、私の item_numbers テーブルからのオブジェクトの配列です。それらに適用する .mount メソッドは、別のテーブルで item_number の値を検索し、それを BigDecimal オブジェクトとして返します。明らかに、inject メソッドは、返されたすべての i.mount オブジェクトを追加します。これは問題なく機能します。

このステートメントを

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

私の信頼できるつるはしの本によると、これらは同等であるはずです。i.mount が BigDecimal だからですか?もしそうなら、なぜ今それが機能するのですか?そうでない場合は、なぜ機能しないのですか。

4

3 に答える 3

18

API で読み取ることができるもの:

memo の初期値を明示的に指定しない場合は、コレクションの最初の要素が memo の初期値として使用されます。

そのため、item_numbers[0] が初期値として指定されますが、これは数値ではなく、オブジェクトです。エラーが発生しました

未定義のメソッド `+'。

そのため、初期値を 0 に指定する必要があります

item_numbers.inject(0){ |合計, i| 合計 + i }

于 2010-03-22T11:58:01.803 に答える
8

i.amountそれは、プレーンではなくアクセスしているためですi。動作しないバージョンでは、暗黙のうちにitem_numbers[0] + item_numbers[1].amount + ....

省略形の 1 つはですが、列挙子が返されないitem_numbers.map(&:amount).inject(&:+)場合、その方法ではリストに対して 2 つの反復が発生する可能性があります。map

それでも納得できない場合はamount、値を返す前に値を出力するメソッドを Fixnum で定義すると、何が出力されるかを見てください。

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開始値が明示的に渡されていない場合、 が最初の要素で呼び出されないことがはっきりとわかります。

于 2010-03-22T11:15:36.007 に答える