2009-07-23 12 views
4

次のように@housesアレイが設定されていると仮定:集合住宅の平均住宅価格を簡潔にどのように把握していますか?

house1.price = 10 
house2.price = 20 
house3.price = 30 
@houses << house1 
@houses << house2 
@houses << house3 

これが私たちの計算の出発点であり、我々は住宅の平均価格を検索する:

total = 0 
average = 0 
for h in @houses 
total += h.price 
end 
average = total/@houses.size 

これはのように思えるが平均を取るためにかなりたくさんのタイピングが必要です。

良い方法がありますか?

答えて

14

列挙可能なコレクションに対してinjectメソッドを使用します。 Injectは 'accumulator'(この場合は0)の初期値を渡し、リスト内の各要素に何らかの操作を適用し、アキュムレータが次の反復に渡される新しい値を返します。

アキュムレータの最終値は、injectコールから返されます。

この場合、すべての住宅価格をアキュムレータに加算し、最後に合計数で除算するだけです。

Rubyのskillzではもっと楽しくなりますが、これはかなりわかりやすくなりますが、これは合理的に理解でき、値を追加するために一度リストを反復するだけです。

@houses.inject(0){|total, house| total + house.price}/@houses.size 
11

Madlepの回答は、過去数年間のRubyのどのバージョンでも動作します。しかし、Ruby 1.8.7以降を使用している場合は、@houses.collect(&:price).inject(:+)/@houses.sizeというように少し簡潔に表現できます。

ちなみに、このテクニックは2回繰り返す必要があるため、この手法は遅くなると思っていましたが、Ruby自体の最適化のおかげで、実際にはRuby 1.8.7のテストでは数百万件Ruby 1.9で過去1,000万件ものアイテムでさえ(ただしそれほど多くはない)。プロファイリングの重要性を示すために移動します。

+0

こんにちはチャック。私はあなたがここで与えた構文の説明については "Rubyプログラミング言語"を見てきましたが、私はそれらの特殊文字が何であるか把握できません。あなたは、価格が何を意味するかを教えてもらえますか、注射するか(:+)ありがとう。 –

+6

Ruby 1.8.7と1.9の新機能です。ブロックを受け取るメソッドの場合、 '&:somemethod'を渡すことができます。これは' {| object |オブジェクト。ソームメソッド} '。 ':+'に関しては、 'inject {| memo、obj | '}のように、配列内のすべてのオブジェクトに対して' + 'を呼び出すようにinjectに指示します。メモ+ obj} '。それは理にかなっていますか? – Chuck

+1

1.9に追加したことがわかりませんでした。素晴らしい:D – madlep

0

あなたがRailsアプリケーションの場合は、array.sum/array.sizeを実行できます。

+0

'.sum'は数値の配列であれば動作します。あなたが質問を読むと、OPには数字ではなく家のオブジェクトの配列があります。 –

関連する問題