ruby 如何在Ruby中对数组中的对象的属性求和
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11272929/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to sum properties of the objects within an array in Ruby
提问by Spike Fitsch
I understand that in order to sum array elements in Ruby one can use the inject method, i.e.
我知道为了在 Ruby 中对数组元素求和,可以使用注入方法,即
array = [1,2,3,4,5];
puts array.inject(0, &:+)
But how do I sum the properties of objects within an object array e.g.?
但是我如何总结对象数组中对象的属性,例如?
There's an array of objects and each object has a property "cash" for example. So I want to sum their cash balances into one total. Something like...
例如,有一个对象数组,每个对象都有一个属性“现金”。所以我想把他们的现金余额加在一起。就像是...
array.cash.inject(0, &:+) # (but this doesn't work)
I realise I could probably make a new array composed only of the property cash and sum this, but I'm looking for a cleaner method if possible!
我意识到我可能会创建一个仅由财产现金组成的新数组并将其求和,但如果可能的话,我正在寻找一种更清洁的方法!
回答by Yuri Barbashov
array.map(&:cash).inject(0, &:+)
or
或者
array.inject(0){|sum,e| sum + e.cash }
回答by Hymanlin
In Ruby On Rails you might also try:
在 Ruby On Rails 中,您也可以尝试:
array.sum(&:cash)
array.sum(&:cash)
Its a shortcut for the inject business and seems more readable to me.
http://api.rubyonrails.org/classes/Enumerable.html
它是注入业务的捷径,对我来说似乎更具可读性。
http://api.rubyonrails.org/classes/Enumerable.html
回答by Theo
#reducetakes a block (the &:+is a shortcut to create a proc/block that does +). This is one way of doing what you want:
#reduce接受一个块(这&:+是创建一个 proc/block 的快捷方式+)。这是做你想做的一种方式:
array.reduce(0) { |sum, obj| sum + obj.cash }
回答by vicocas
Most concise way:
最简洁的方法:
array.map(&:cash).sum
If the resulting array from the map has nil items:
如果来自地图的结果数组有 nil 项:
array.map(&:cash).compact.sum
回答by Christopher Oezbek
If start value for the summation is 0, then sum alone is identical to inject:
如果总和的起始值为 0,则 sum 本身与注入相同:
array.map(&:cash).sum
And I would prefer the block version:
我更喜欢块版本:
array.sum { |a| a.cash }
Because the Proc from symbol is often too limited (no parameters, etc.).
因为 Proc from 符号通常太有限(没有参数等)。
(Needs Active_Support)
(需要 Active_Support)
回答by mpospelov
Here some interesting benchmarks
这里有一些有趣的基准
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
And results
和结果
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
As you can see inject a little bit faster
正如你所看到的,注入速度要快一点
回答by megas
There's no need to use initial in inject and plus operation can be shorter
不需要在注入中使用初始值,并且加号操作可以更短
array.map(&:cash).inject(:+)

