Как исправить ошибку «String to Integer» в Ruby - PullRequest
2 голосов
/ 02 ноября 2019

Мне нужно, чтобы стоимость доставки определялась по разным ставкам.

Я пробовал мешанину вещей за последние 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

Результат должен показывать стоимость доставки после применения ставки. Я продолжаю получать сообщение об ошибке String to Integer.

Ответы [ 2 ]

2 голосов
/ 02 ноября 2019

Проблема в том, что одна или несколько переменных в умножении представляют собой строку, которая приводит к ошибке 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. Создав диапазон от min до max и спросив, включает ли он значение веса, вы можете присвоить ему значение:

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 голос
/ 03 ноября 2019

Менее многословное и более идиоматически правильное решение заключается в использовании оператора 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

Если вы хотите использовать такие диктовки, как Себастьян Пальма, вы можете вместо этого использовать хеш с диапазонами для ключей:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...