我是Rails(和ruby)的新手。迭代数组以求变量的标准方法是什么?
e.g。对于一个月的总费用,首先是一个数组:
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方法的最后一行,所以必须有更好的方法来编写它吗?
答案 0 :(得分:4)
像Doug建议的那样,inject
方法会很有效。但是,如果可以的话,通常最好在数据库中执行此类操作。 ActiveRecord为此提供了一个简单的界面。
total = Expenses.sum :cost, :conditions => {
:date => (Date.today.beginning_of_month..Date.today.end_of_month)
}
请注意,您也可以使用Range对象而不是SQL插值。
如果你因为其他原因加载了所有的Expense对象,那么注入方法当然没问题。
答案 1 :(得分:3)
您正在寻找Enumerable#inject
方法:
expenses_this_month.inject(0.0) {|total, expense| total + expense }
此方法(从Smalltalk借用)获取传递给它的值(在本例中为0.0)并将内部变量设置为该值。然后它使用该变量的值(作为total
)和每个连续的元素(作为expense
)调用块,并将变量设置为块返回的任何值(在这种情况下是总和的总和)和当前元素。)
您可能希望将此计算卸载到数据库中,正如kejadlen建议的那样,使用#sum
方法。
答案 2 :(得分:3)
expenses_this_month.map(&:cost).sum
(更短,虽然它在内存中创建一个不像reduce的数组)
expenses_this_month.reduce(BigDecimal.new('0')) { |total, expense| total + expense.cost }
你需要记住将初始值传递给reduce(否则它将为空数组返回nil)并在处理钱时使用BigDecimal而不是常规浮点数。
答案 3 :(得分:2)
返回数据后,请使用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])
答案 4 :(得分:1)
如果您正在使用Rails,则可以使用内置的sum
类方法(假设Expense
是类名)。
expenses_this_month = Expense.sum('cost',
:conditions => ['date >= ? and date <= ?',
Date.today.beginning_of_month,
Date.today.end_of_month])