在Ruby中编写此计算的最佳方法?

时间:2010-08-25 19:17:40

标签: ruby

在Ruby中编写此计算的最佳方法是什么?

amt = self.alt_inv - (self.alt_tax ? self.alt_tax : 0)
    - (self.alt_freight ? self.alt_freight : 0)
    - (self.misc1_amt ? self.misc1_amt : 0)
    - (self.misc2_amt ? self.misc2_amt : 0)

7 个答案:

答案 0 :(得分:8)

在Ruby中,如果某些内容不是nil,它将在布尔表达式中返回true,并在计算中返回其值。

我不是很好解释,但你可以这样做:

amt = alt_inv - 
  (alt_tax     || 0) -
  (alt_freight || 0) -
  (misc1_amt   || 0) -
  (misc2_amt   || 0)

这是一种更简洁的方式来处理您最初使用的三元组。


编辑:

我实际上比Jed Schneider的回答更好。我不会在这里复制它,因为他的答案值得赞扬它的优雅。

答案 1 :(得分:6)

由于amt是所有属性之和与alt_inv之间的差异,因此您可以对推算进行求和,然后从alt_inv中减去。 reduce提供了一种干净的方法来做到这一点。 compact会在执行缩减之前删除所有nil值。

当然,在这种情况下,属性可以扩展到您需要的任何内容,甚至可以从数据中动态创建,在现实生活中,我显然不会使用变量属性。

attributes = [alt_tax, alt_freight, misc1_amt, misc2amt]
amt = alt_inv - attributes.compact.reduce(:+)

减少:http://apidock.com/ruby/Enumerable/reduce

契约:http://apidock.com/ruby/Array/compact

答案 2 :(得分:5)

如果在创建对象时自动将对象的值初始化为0(如果构造函数中未提供这些值),则可能更清晰。否则,您需要在对象中的任何位置执行此类条件逻辑,这些值是必需的。你宁愿这样做吗?

amt = alt_inv - alt_tax - alt_freight - misc1_amt - misc2_amt 

答案 3 :(得分:1)

如果您没有名称相同的局部变量,而不是self.alt_tax,则只需alt_tax而不用self.

||运算符返回第一个操作数时,它不是nil,否则返回第二个操作数,所以代替:

alt_tax ? alt_tax : 0

你可以写:

alt_tax || 0

答案 4 :(得分:1)

Jed解决方案的一些变化,这不是不必要的复杂,但更简洁恕我直言。

使用compactinjectreduce的最常见同义词)并不复杂,并且在Ruby程序员中得到了充分利用:

amt = [alt_tax, alt_freight, misc1_amt, misc2_amt].inject(alt_inv) do |result, attribute|
  result - (attribute || 0)
end

或:

amt = alt_inv - [alt_freight, misc1_amt, misc2_amt].compact.inject{|sum, n| sum + n }

如果您对该语法感到不舒服,这是另一种编写inject(&:+)的方法。 如果您使用的是Rails,则可以使用sum方法或implement it yourself替换注入。

答案 5 :(得分:0)

除了以下两个例外,我看起来没问题:

1)Ruby对语句结尾做出假设。

amt = self.alt_inv - (self.alt_tax ? self.alt_tax : 0)

本身就是一个有效的语句,你需要在前一行保留减号或者转义换行符。

2)除了左侧任务外,Ruby假定“自己”为所有者。我建议:

amt = alt_inv - 
  (alt_tax     ? alt_tax     : 0) -
  (alt_freight ? alt_freight : 0) -
  (misc1_amt   ? misc1_amt   : 0) -
  (misc2_amt   ? misc2_amt   : 0)

答案 6 :(得分:0)

amt = alt_inv - alt_tax.to_f - alt_freight.to_f - misc1_amt.to_f - misc2_amt.to_f
nil.to_f = 0.0