这个数字如何对英文单词代码起作用,Ruby

时间:2015-05-17 00:16:15

标签: ruby string methods integer

因此,在寻找能够获取整数并返回该整数的字符串值的方法时,我找到了这个解决方案:

   def in_words(int)
      numbers_to_name = {
          1000000 => "million",
          1000 => "thousand",
          100 => "hundred",
          90 => "ninety",
          80 => "eighty",
          70 => "seventy",
          60 => "sixty",
          50 => "fifty",
          40 => "forty",
          30 => "thirty",
          20 => "twenty",
          19=>"nineteen",
          18=>"eighteen",
          17=>"seventeen", 
          16=>"sixteen",
          15=>"fifteen",
          14=>"fourteen",
          13=>"thirteen",              
          12=>"twelve",
          11 => "eleven",
          10 => "ten",
          9 => "nine",
          8 => "eight",
          7 => "seven",
          6 => "six",
          5 => "five",
          4 => "four",
          3 => "three",
          2 => "two",
          1 => "one"
        }
      str = ""
      numbers_to_name.each do |num, name|
        if int == 0
          return str
        elsif int.to_s.length == 1 && int/num > 0
          return str + "#{name}"      
        elsif int < 100 && int/num > 0
          return str + "#{name}" if int%num == 0
          return str + "#{name} " + in_words(int%num)
        elsif int/num > 0
          return str + in_words(int/num) + " #{name} " + in_words(int%num)
        end
      end
    end

这个答案很棒,因为它为我提供了一个关于我想要做什么的答案。但是,我很新,并不完全明白它是如何工作的。我确实理解哈希,但我不明白作者如何在哈希下面构造他的代码。我试图减少这些代码并逐行测试,但是当我这样做时它不起作用。我只想弄清楚他们为什么/如何执行int/num之类的事情,并在他们的块代码中间使用他们的方法in_words

如果有人有时间一步一步地解决这个问题,并解释这段代码是如何运作的,我将非常感激。注意:我会对原始作者的解决方案做出评论,但我不被允许,因为我没有足够的“声誉”这样做。

2 个答案:

答案 0 :(得分:3)

# Loop through the hash, `num` is the hash key, `name` is the hash value
numbers_to_name.each do |num, name|

   # Zero is not used in the lookup table, so return an empty string if that 
   # was an argument supplied to the function (e.g., in_words(0) )
   if int == 0
      return str

   # If it's a single digit number (e.g., `6`) and is equal to the key (e.g., 6/6 == 1)
   # then return the word/name 
   elsif int.to_s.length == 1 && int/num > 0
     return str + "#{name}"

   # If your supplied number was less than a hundred (e.g., `50`)
   elsif int < 100 && int/num > 0
      return str + "#{name}" if int%num == 0

   # If your supplied number was something like `57` you would return `fifty` and 
   # then need to convert the `7` to `seven`, so call the function 
   # again ( 57%50 has a remainder of 7, so in_words(7) translate the 7)
      return str + "#{name} " + in_words(int%num)

   # For instance, 567 => five hundred sixty seven:
    elsif int/num > 0
      return str + in_words(int/num) + " #{name} " + in_words(int%num)
    end

 end

这里有一个递归问题,这就是为什么你看到in_words在多个地方被调用的原因。

我认为一个重要的注意事项是导入哈希键的方式(从最大到最小)。在Ruby 1.9+中,枚举哈希键以便保持它们的顺序。鉴于代码的逻辑,每次循环时,它都会接受产生正结果的第一个键。

举一个例子,有很多地方使用int/num > 0。如果你的数字是6,那么它将首先针对1000000进行测试。6/1000000将导致0,因为分子和分母都是整数。使用整数很重要,因为6/1000000.0会导致浮点数并且大于0(并且if语句将为true - bad)。这意味着它将继续迭代键(从最大的输入顺序到最小的输入顺序),并且它到达匹配的第一个将是你想要的那个。

举一个以相反顺序(从最小到最大)排序的哈希的例子,想象你想把5翻译成一个单词。 5.to_s.length == 1是真的,但那时int/num > 0。在这种情况下,int5,您的第一个密钥为1; 5 / 1大于零,因此评估为true并返回散列one中的值。换句话说,in_words(5)会返回one,这是不正确的。在代码中找到的哈希顺序(从最大到最小)将迭代所有键5/10000000 ... 5/6,它们都等于0,但随后到达第一个大于零的分区(5 / 5 == 1)并且具有所需的价值。

答案 1 :(得分:0)

肯定有更快/更清晰的方法来实现这一点,并且递归完全被误导但是......

#loop thru all the items in the hash and assign the hey to num and val to name
numbers_to_name.each do |num, name|
    # if the input parameter is zero return str which is ""
    if int == 0
      return str

    # if the length of the string representation of the input parameter is 1 and an empty string divided by the current key is larger than 0 return str + name (this is insane)
    elsif int.to_s.length == 1 && int/num > 0
      return str + "#{name}"

    # if the key value is less than 100 and an empty string divided by the current key is larger than 0 return str + name if the modulus of key and num is 0, if not? return "" + in_words(int%num) (this is also insane)    
    elsif int < 100 && int/num > 0
      return str + "#{name}" if int%num == 0
      return str + "#{name} " + in_words(int%num)

    # if the input parameter divided by the key is larger than 0 return "" + the result of this function with the key/num as input + the current items value + in_words(int%num)
    elsif int/num > 0
      return str + in_words(int/num) + " #{name} " + in_words(int%num)
    end
  end

我的眼睛现在正在流血,但这正是发生的事情。