我需要根据各种费率确定运费。
过去5个小时,我尝试了大杂烩。 如果我应该使用.to_s .to_f,则我尝试并这样做不正确。
if (weight < 2)
rate = 0.10
elsif ((weight >= 2) or (weight < 10))
rate = 0.20
elsif ((weight >= 10) or (weight < 40))
rate = 0.30
elsif ((weight >= 40) or (weight < 70))
rate = 0.50
elsif ((weight >= 70) or (weight < 100))
rate = 0.75
else (weight >= 100)
rate = 0.90
end
rate = rate.to_i
ship_cost = weight * price * rate
ship_cost = ship_cost.to_i
应用费率后,结果应该显示出运输成本。我不断遇到“字符串到整数”错误。
答案 0 :(得分:2)
问题是乘法中的一个或多个变量是一个字符串,这会导致您得到TypeError
错误,例如:
'a' * 'b' # '*': no implicit conversion of String into Integer (TypeError)
如果要抑制该错误,可以将其手动转换为整数或浮点数。这意味着如果字符串没有数字表示,它将返回0:
'asd'.to_i # 0
'1'.to_i. # 1
'-9.9'.to_i # -9
'-9.9'.to_f # -9.9
或者,您可以使用“字典”来处理rate
分配,该字典包含最小值和最大值weight
可以返回X
。创建一个从最小到最大的范围,并询问它是否包含权重值,您可以为其分配值:
dict = {
[-Float::INFINITY, 2] => 0.10,
[2, 10] => 0.20,
[10, 40] => 0.30,
[40, 70] => 0.50,
[70, 100] => 0.75,
[100, Float::INFINITY] => 0.90
}
p dict.find { |(start, finish), _| (start...finish).include?(-42.12) }.last # 0.1
p dict.find { |(start, finish), _| (start...finish).include?(0) }.last # 0.1
p dict.find { |(start, finish), _| (start...finish).include?(1) }.last # 0.1
p dict.find { |(start, finish), _| (start...finish).include?(23) }.last # 0.3
p dict.find { |(start, finish), _| (start...finish).include?(101) }.last # 0.9
答案 1 :(得分:1)
一个不太冗长和习惯用法更正确的解决方案是使用带有范围的case语句:
def shipping_rate(weight)
case weight
when 0...2
0.10
when 2...10
0.20
when 10...40
0.30
when 40...70
0.50
when 70...100
0.75
when 100...Float::INFINITY
0.90
end
end
使用...
声明范围会排除最终值。 (40...70).cover?(70) == false
这样。这样我们就可以避免重叠问题。
require "minitest/autorun"
class TestShippingRate < Minitest::Test
def test_correct_rate
assert_equal 0.10, shipping_rate(1)
assert_equal 0.20, shipping_rate(3)
assert_equal 0.30, shipping_rate(39)
assert_equal 0.50, shipping_rate(40)
assert_equal 0.75, shipping_rate(70)
assert_equal 0.90, shipping_rate(101)
end
end
# Finished in 0.002255s, 443.3896 runs/s, 2660.3374 assertions/s.
# 1 runs, 6 assertions, 0 failures, 0 errors, 0 skips
如果您想使用塞巴斯蒂安·帕尔玛(Sebastian Palma)建议的字典,则可以使用带有键范围的哈希来代替:
def shipping_rate(weight)
{
0...2 => 0.10,
2...10 => 0.20,
10...40 => 0.30,
40...70 => 0.50,
70...100 => 0.75,
100...Float::INFINITY => 0.90
}.find { |k, v| break v if k.cover? weight }
end
使用case
稍微灵活一点,尽管您可以添加一个else
条件或处理字符串参数:
def shipping_rate(weight)
case weight
when 0...2
0.10
when 2...10
0.20
when 10...40
0.30
when 40...70
0.50
when 70...100
0.75
when 100...Float::INFINITY
0.90
# I'm not saying this is a good idea as the conversion should happen
# upstream. Its just an example of what you can do
when String
shipping_rate(weight.to_f) # recursion
else
raise "Oh noes. This should not happen."
end
end