53

Rubyで配列要素を合計するには、injectメソッドを使用できることを理解しています。

array = [1,2,3,4,5];
puts array.inject(0, &:+) 

しかし、オブジェクト配列内のオブジェクトのプロパティを合計するにはどうすればよいですか?

オブジェクトの配列があり、各オブジェクトにはたとえば「現金」というプロパティがあります。そこで、彼らの現金残高を 1 つの合計にまとめたいと思います。何かのようなもの...

array.cash.inject(0, &:+) # (but this doesn't work)

おそらくプロパティキャッシュのみで構成された新しい配列を作成してこれを合計できると思いますが、可能であればよりクリーンな方法を探しています!

4

7 に答える 7

69
array.map(&:cash).inject(0, &:+)

また

array.inject(0){|sum,e| sum + e.cash }
于 2012-06-30T09:13:57.343 に答える
58

Ruby On Rails では、次のことも試すことができます。

array.sum(&:cash)

これは注入ビジネスのショートカットであり、私には読みやすいようです。
http://api.rubyonrails.org/classes/Enumerable.html

于 2013-12-17T21:01:54.420 に答える
11

#reduceブロックを取ります (&:+は、 を実行する proc/block を作成するためのショートカットです+)。これは、あなたが望むことをする1つの方法です:

array.reduce(0) { |sum, obj| sum + obj.cash }
于 2012-06-30T09:15:14.050 に答える
4

最も簡潔な方法:

array.map(&:cash).sum

マップから得られた配列に nil 項目がある場合:

array.map(&:cash).compact.sum
于 2015-11-02T20:47:34.690 に答える
2

ここにいくつかの興味深いベンチマークがあります

array = Array.new(1000) { OpenStruct.new(property: rand(1000)) }

Benchmark.ips do |x|
  x.report('map.sum') { array.map(&:property).sum }
  x.report('inject(0)') { array.inject(0) { |sum, x| sum + x.property } }
  x.compare!
end

そして結果

Calculating -------------------------------------
             map.sum   249.000  i/100ms
           inject(0)   268.000  i/100ms
-------------------------------------------------
             map.sum      2.947k (± 5.1%) i/s -     14.691k
           inject(0)      3.089k (± 5.4%) i/s -     15.544k

Comparison:
           inject(0):     3088.9 i/s
             map.sum:     2947.5 i/s - 1.05x slower

ご覧のとおり、注入が少し速くなります

于 2016-12-12T18:17:59.683 に答える
2

合計の開始値が 0 の場合、合計のみは注入と同じです。

array.map(&:cash).sum

そして、私はブロックバージョンを好むでしょう:

array.sum { |a| a.cash }

Proc from シンボルはしばしば制限されすぎているためです (パラメーターがないなど)。

(Active_Support が必要)

于 2016-08-08T00:25:16.583 に答える
1

inject で initial を使用する必要はなく、さらに操作を短くすることができます

array.map(&:cash).inject(:+)
于 2012-06-30T10:58:29.867 に答える