TL;DR: 考えられる解決策の 1 つ
def compute_average(*values)
# This makes sure arrays get flattened to a single array.
values.flatten!
# Throws away all nil values passed as arguments.
values.reject!(&:nil?)
# Throws away all non-numeric values.
# This includes trashing strings that look like numbers, like "12".
values.keep_if{ |v| v.is_a? Numeric }
total = values.sum.to_f
return Float::NAN if total.zero?
# I'm not sure what this business is
# average = [a, 2*b, 3*c, 4*d, 5*e].sum / total
# but it can be translated to
average = values.each_with_index.map{ |v,i| v*(i+1) }.sum / total
average.round(2)
end
これにより、すべてのケースから保護されます。
compute_average(1,2,3,4,5)
=> 3.67
compute_average(0,0,0,0,0)
=> NaN
compute_average(1,2,nil,4,5)
=> 3.08
compute_average(1,2,"string",4,5)
=> 3.08
compute_average(1)
=> 1.0
compute_average([1,2,3,4,5])
=> 3.67
compute_average
=> NaN
元の機能:
def compute_average(a,b,c,d,e)
total = [a,b,c,d,e].sum.to_f
average = [a, 2*b, 3*c, 4*d, 5*e].sum / total
average.round(2)
end
ゼロをチェックすることを検討してください。
def compute_average(a,b,c,d,e)
total = [a,b,c,d,e].sum.to_f
return if total.zero?
average = [a, 2*b, 3*c, 4*d, 5*e].sum / total
average.round(2)
end
この変更は、次の 1 つのケースのみを保護します。
compute_average(1,2,3,4,5)
# => 3.67
compute_average(0,0,0,0,0)
# => nil
compute_average(1,2,nil,4,5)
# => TypeError: NilClass can't be coerced into Fixnum
compute_average(1,2,"string",4,5)
# => TypeError: String can't be coerced into Fixnum
compute_average(1)
# => ArgumentError: wrong number of arguments calling `compute_average` (1 for 5)
compute_average([1,2,3,4,5])
# => ArgumentError: wrong number of arguments calling `compute_average` (1 for 5)
compute_average
# => ArgumentError: wrong number of arguments calling `compute_average` (0 for 5)
インラインの使用を検討するrescue
def compute_average(a,b,c,d,e)
total = [a,b,c,d,e].sum.to_f
average = [a, 2*b, 3*c, 4*d, 5*e].sum / total rescue 0
average.round(2)
end
この変更は、1 つのケースに対してのみ保護します。
compute_average(1,2,3,4,5)
# => 3.67
compute_average(0,0,0,0,0)
# => NaN
compute_average(1,2,nil,4,5)
# => TypeError: NilClass can't be coerced into Fixnum
compute_average(1,2,"string",4,5)
# => TypeError: String can't be coerced into Fixnum
compute_average(1)
# => ArgumentError: wrong number of arguments calling `compute_average` (1 for 5)
compute_average([1,2,3,4,5])
# => ArgumentError: wrong number of arguments calling `compute_average` (1 for 5)
compute_average
# => ArgumentError: wrong number of arguments calling `compute_average` (0 for 5)
インラインを使用すると、rescue
別の結果が生じます。このタイプミスを考えてみましょう:
def compute_average(a,b,c,d,e)
total = [a,b,c,d,e].sum.to_f
average = [a, 2*b, 3*c, 4*d, 5*e].smu / total rescue 0
# ^^^
average.round(2)
end
compute_average(1,2,3,4,5)
# => 0.0
compute_average(0,0,0,0,0)
# => 0.0
を使用することを検討してくださいrescue
def compute_average(a,b,c,d,e)
total = [a,b,c,d,e].sum.to_f
average = [a, 2*b, 3*c, 4*d, 5*e].sum / total
average.round(2)
rescue ZeroDivisionError
0.0
end
これはエラーを隠しませんが、上記の傾斜と同じシナリオから保護するため、より優れていrescue
ます。
私が通常の平均計算と呼ぶ別のバージョン
補足として、私がよく知っている平均操作は、合計/カウントを使用して計算されるため、それを行うバージョンを次に示します。
def compute_average(*values)
# This makes sure arrays get flattened to a single array.
values.flatten!
# Throws away all nil values passed as arguments.
values.reject!(&:nil?)
# Throws away all non-numeric values.
# This includes trashing strings that look like numbers, like "12".
values.keep_if{ |v| v.is_a? Numeric }
total = values.sum.to_f
count = values.count
return Float::NAN if count.zero?
total / count
end
これにより、すべてのケースから保護されます。
compute_average(1,2,3,4,5)
=> 3.0
compute_average(0,0,0,0,0)
=> 0.0
compute_average(1,2,nil,4,5)
=> 3.0
compute_average(1,2,"string",4,5)
=> 3.0
compute_average(1)
=> 1.0
compute_average([1,2,3,4,5])
=> 3.0
compute_average
=> NaN