如何在Ruby中对数组中对象的属性求和

Spi*_*sch 46 ruby arrays sum object inject

我理解为了在Ruby中对数组元素求和,可以使用inject方法,即

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

但是如何在对象数组中求和对象的属性呢?

有一个对象数组,每个对象都有一个属性"现金",例如.所以我想将他们的现金余额总计为一个.就像是...

array.cash.inject(0, &:+) # (but this doesn't work)
Run Code Online (Sandbox Code Playgroud)

我意识到我可能会创建一个仅由物业现金组成的新阵列,并总结一下,但如果可能的话,我正在寻找一种更清洁的方法!

Yur*_*hov 62

array.map(&:cash).inject(0, &:+)
Run Code Online (Sandbox Code Playgroud)

要么

array.inject(0){|sum,e| sum + e.cash }
Run Code Online (Sandbox Code Playgroud)

  • 这会超过`array`两次,如果有很多元素,这可能是不可取的.为什么不使用适当的块来"注入"?另外`reduce/inject`直接采用符号参数,不需要`Symbol#to_proc` :-) (3认同)
  • Yuri,我给你的答案+1了,但第二个片段看起来不太好,功能更好:`array.inject(0){| sum,e | sum + e.cash}` (3认同)

jac*_*lin 50

在Ruby On Rails中,您可能还会尝试:

array.sum(&:cash)

它是注入业务的捷径,对我来说似乎更具可读性.
http://api.rubyonrails.org/classes/Enumerable.html

  • 更多关于@Dennis的评论:如果你使用的是Rails 4.1+,你就不能在一个activerecord关系上使用``array.sum(&:cash)`,因为它想要一个[ActiveRecord sum](http: //api.rubyonrails.org/classes/ActiveRecord/Calculations.html#method-i-sum)就像这样:`array.sum(:cash)`,它们大不相同(SQL与Ruby).你必须将它转换成一个数组才能使它再次运行:`array.to_a.sum(&:cash)`.相当讨厌! (4认同)
  • 如果你正在使用Rails,这就是你要走的路. (3认同)

The*_*heo 10

#reduce采用一个块(这&:+是创建proc/block的快捷方式+).这是做你想做的事的一种方式:

array.reduce(0) { |sum, obj| sum + obj.cash }
Run Code Online (Sandbox Code Playgroud)

  • @Nerian:在Smalltalk中,这被称为`inject:into:`,而其他几种语言称为折叠`reduce`(例如Clojure,Common Lisp,Perl,Python).别名是为了容纳不同背景的人.对于`map` /`collect`也是如此. (3认同)
  • `#increration'是1.9+中的`#injection`的别名,顺便说一下. (2认同)

小智 5

最简洁的方式:

array.map(&:cash).sum
Run Code Online (Sandbox Code Playgroud)

如果地图中生成的数组有 nil 项:

array.map(&:cash).compact.sum
Run Code Online (Sandbox Code Playgroud)