我正在尝试重构一个写得很差的方法。该方法用于扫描包含如下所示的余额哈希的数组:
{ 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
但是要做到这一点还有更简洁的方法。我如何重构这个方法,以便它一次遍历原始数组,而不是创建新数组并循环它们?
答案 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(&:+)
一开始看起来有点密集,但一旦熟悉这些习语就会变得清晰。