鉴于我想进行以下计算:
total = subtotal - discount
由于discount
可能大于subtotal
,因此代码如下:
class Calculator
def initialize(subtotal: subtotal, discount: discount)
@subtotal = subtotal
@discount = discount
end
def total
[subtotal - discount, 0].max
end
private
def subtotal
@subtotal
end
def discount
@discount
end
end
当看到[subtotal - discount, 0].max
部分或任何类似的代码时,我经常需要停下来思考。
有更优雅的方式来处理这种计算吗?
答案 0 :(得分:1)
认为我们可以扩展Numeric
类?
class Numeric
def non_negative
self > 0 ? self : 0
end
end
class Calculator
def initialize(subtotal: subtotal, discount: discount)
@subtotal = subtotal
@discount = discount
end
def total
(@subtotal - @discount).non_negative
end
end
答案 1 :(得分:1)
我认为您的解决方案本质上是正确的,除了进行少量重构外,可能是最具可读性的。我可能会像这样稍微更改它:
def total
final_total = subtotal - discount
[final_total, 0].max
end
红宝石表达式[final_total, 0].max
本质上是针对同一功能max {final_total, 0}
的传统数学解决方案。区别只是符号和上下文。一旦看到此最大表达式一次或两次,就可以按以下方式读取它:“ final_total,但至少为零”。
如果您多次使用此表达式,则可以添加另一个at_least_zero
方法或Shiko解决方案中的类似方法。
答案 2 :(得分:0)
简单if
声明可能更容易理解:
def total
if discount > subtotal
0
else
subtotal - discount
end
end
答案 3 :(得分:0)
为了澄清更多,我们需要在 core_ext.rb 中添加要扩展的类。文件:
1)在项目的 config \ initializers 文件夹下创建 core_ext.rb 文件。
2)如@songyy在回答中所述粘贴以下内容:
class Numeric
def non_negative
self > 0 ? self : 0
end
end
参考:
https://guides.rubyonrails.org/plugins.html#extending-core-classes
答案 4 :(得分:0)
一些性能数字:
user system total real
[i, 0.0].max 0.806408 0.001779 0.808187 ( 0.810676)
0.0 if i < 0.0 0.643962 0.001077 0.645039 ( 0.646368)
0.0 if i.negative? 0.625610 0.001680 0.627290 ( 0.629439)
代码:
require 'benchmark'
n = 10_000_000
Benchmark.bm do |benchmark|
benchmark.report('[value, 0.0].max'.ljust(18)) do
n.times do |i|
a = [-1*i, 0.0].max
end
end
benchmark.report('0.0 if value < 0.0'.ljust(18)) do
n.times do |i|
a = 0.0 if -1*i < 0.0
end
end
benchmark.report('0.0 if value.negative?'.ljust(18)) do
n.times do |i|
a = 0.0 if (-1*i).negative?
end
end
end