Ruby on rails数组迭代

时间:2010-01-08 01:47:35

标签: ruby-on-rails ruby

我是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方法的最后一行,所以必须有更好的方法来编写它吗?

5 个答案:

答案 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])