如何简化总和月度余额的枚举方法

时间:2013-10-14 02:35:37

标签: ruby enums big-o

我正在尝试重构一个写得很差的方法。该方法用于扫描包含如下所示的余额哈希的数组:

{ amount: $123, month_end: '2013-01-31' }

并返回同月末的所有余额,然后总结金额。

def monthly_total(month)
  balances = [ balance_1, balance_2 ]
  # get and array of balances
  balances_for_month = balances.select do |balance|
    balance.month_end == month
  end
  # grab only the balances for the desired month
  balance_amounts = balances_for_month.map do |balance|
    balance.amount
  end
  #take all the balances for the month and sum them.
  balance_amounts.inject{|sum,x| sum + x }
end

但是要做到这一点还有更简洁的方法。我如何重构这个方法,以便它一次遍历原始数组,而不是创建新数组并循环它们?

1 个答案:

答案 0 :(得分:1)

这是一个很好的代码。变量名称很好,意图很明显。

两次通过阵列没有任何问题。 Ruby更多的是让你的意图明确,而不是关于最快的代码。你应该只在知道代码不够快的时候进行优化,然后你应该测量,以确保你真正让它更快。当你做一些你认为可以加快速度的事情时,Ruby经常会让你感到惊讶。

第二个循环(将余额转换为balance.amount)可以缩短为:

balances_amounts = balances_for_month.map(&:amount)

总和可以缩短为:

balance_amounts.inject(&:+)

有关这些方法如何运作的说明,请参阅What does to_proc method mean?

有时临时性会增加代码的清晰度;有时不。一旦你使用了上述技术,临时工就可以摆脱,留下:

balances.select do |balance|
  balance.month_end == month
end.map(&:amount).inject(&:+)

一开始看起来有点密集,但一旦熟悉这些习语就会变得清晰。