[英]Ruby on rails array iteration
我是Rails(和ruby)的新手。 遍历数组以累加变量的标准方法是什么?
例如,对于一个月的总费用,首先是一个数组:
expenses_this_month = expenses.find :all,
:conditions => ['date >= ? and date <= ?',
Date.today.beginning_of_month, Date.today.end_of_month]
我已经知道这样做的两种方式:
total = 0.0
for expense in expenses_this_month
total += expense.cost
end
return total
或带块
total = 0.0
expenses_this_month.each do |expense|
total += expense.cost
end
return total
我知道ruby方法的最后一行将默认返回,因此必须有更好的编写方法吗?
inject
方法会很好用,就像Doug建议的那样。 但是,通常最好在可能的情况下在数据库中执行类似的操作。 ActiveRecord为此提供了一个简单的界面。
total = Expenses.sum :cost, :conditions => {
:date => (Date.today.beginning_of_month..Date.today.end_of_month)
}
请注意,您还可以使用Range对象代替SQL插值。
如果由于其他原因要加载所有Expense对象,则注入方法当然可以。
您正在寻找Enumerable#inject
方法:
expenses_this_month.inject(0.0) {|total, expense| total + expense }
此方法(从Smalltalk借用)采用传递给它的值(在这种情况下为0.0),并为此设置内部变量。 然后,它将使用该变量的值(作为total
)和每个后续元素(作为expense
)的值调用该块,并将变量设置为该块返回的值(在这种情况下,total和当前元素之和)。
但是,正如kejadlen所建议的那样,您可能希望通过使用#sum
方法将此计算卸载到数据库中。
expenses_this_month.map(&:cost).sum
(较短,尽管它与reduce不同,但是在内存中创建了一个数组)
expenses_this_month.reduce(BigDecimal.new('0')) { |total, expense| total + expense.cost }
您需要记住传递一个初始值来减少(否则它将为空数组返回nil),并在处理货币时使用BigDecimal而不是常规浮点数。
返回数据后,请使用inject
方法:
total = expenses_this_month.inject { |total, expense| total + expense.cost }
但是,您应该只重写查询:
total = expenses.sum(:cost, :conditions => ['date >= ? and date <= ?',
Date.today.beginning_of_month, Date.today.end_of_month])
如果您使用的是Rails,则可以使用内置的sum
类方法(假设Expense
是类名)。
expenses_this_month = Expense.sum('cost',
:conditions => ['date >= ? and date <= ?',
Date.today.beginning_of_month,
Date.today.end_of_month])
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.