【问题标题】:Using Ruby convert numbers to words?使用 Ruby 将数字转换为单词?
【发布时间】:2013-10-18 08:29:43
【问题描述】:

如何在ruby中将数字转换为单词?

我知道某处有一颗宝石。尝试在没有 gem 的情况下实现它。我只需要数字到英文单词的整数。找到了这个,但是很乱。如果您对如何实现更简洁易读的解决方案有任何想法,请分享。

http://raveendran.wordpress.com/2009/05/29/ruby-convert-number-to-english-word/

这是我一直在做的事情。但是在实施尺度时遇到了一些问题。代码仍然是一团糟。我希望在它正常运行时使其更具可读性。

   class Numberswords
    def in_words(n)

    words_hash = {0=>"zero",1=>"one",2=>"two",3=>"three",4=>"four",5=>"five",6=>"six",7=>"seven",8=>"eight",9=>"nine",
                    10=>"ten",11=>"eleven",12=>"twelve",13=>"thirteen",14=>"fourteen",15=>"fifteen",16=>"sixteen",
                     17=>"seventeen", 18=>"eighteen",19=>"nineteen",
                    20=>"twenty",30=>"thirty",40=>"forty",50=>"fifty",60=>"sixty",70=>"seventy",80=>"eighty",90=>"ninety"}

     scale = [000=>"",1000=>"thousand",1000000=>" million",1000000000=>" billion",1000000000000=>" trillion", 1000000000000000=>" quadrillion"]


    if words_hash.has_key?(n) 
      words_hash[n]

      #still working on this middle part. Anything above 999 will not work
     elsif n>= 1000  
     print  n.to_s.scan(/.{1,3}/) do |number|
            print number
      end



      #print value = n.to_s.reverse.scan(/.{1,3}/).inject([]) { |first_part,second_part| first_part << (second_part == "000" ? "" : second_part.reverse.to_i.in_words) }
      #(value.each_with_index.map { |first_part,second_part| first_part == "" ? "" : first_part + scale[second_part] }-[""]).reverse.join(" ")

    elsif n <= 99
       return [words_hash[n - n%10],words_hash[n%10]].join(" ")
    else
      words_hash.merge!({ 100=>"hundred" })
      ([(n%100 < 20 ? n%100 : n.to_s[2].to_i), n.to_s[1].to_i*10, 100, n.to_s[0].to_i]-[0]-[10])
        .reverse.map { |num| words_hash[num] }.join(" ")
    end
  end
end

#test code
test = Numberswords.new
 print test.in_words(200)

【问题讨论】:

    标签: ruby-on-rails ruby numbers


    【解决方案1】:

    我对此的看法

    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
    
    
    
    puts in_words(4) == "four"
    puts in_words(27) == "twenty seven"
    puts in_words(102) == "one hundred two"
    puts in_words(38_079) == "thirty eight thousand seventy nine"
    puts in_words(82102713) == "eighty two million one hundred two thousand seven hundred thirteen"
    

    【讨论】:

    • 可能要添加检查是否为负if int &lt; 0 /n str &lt;&lt; 'negative ' /n int = int * -1/n end
    • 非常好@NoNonsene !我会在以 ' + in_words(int%/num)' 结尾的两行中添加 (...).strip 以避免在 int=900 等情况下出现尾随空格
    【解决方案2】:

    你考虑过humanize吗?

    https://github.com/radar/humanize

    【讨论】:

      【解决方案3】:

      简单的答案使用humanize gem,你会得到想要的输出

      直接安装

      gem install humanize
      

      或将其添加到您的 Gemfile 中

      gem 'humanize'
      

      你可以使用它

      require 'humanize'
      
      1.humanize       #=> 'one'
      345.humanize     #=> 'three hundred and forty-five'
      1723323.humanize #=> 'one million, seven hundred and twenty-three thousand, three hundred and twenty-three'
      

      如果你在rails中使用这个,你可以直接使用这个

      注意:正如sren 在下面的 cmets 中提到的。 ActiveSupport提供的humanize方法与gem humanize不同

      【讨论】:

      【解决方案4】:

      您也可以使用to_words gem。

      此 Gem 将整数转换为单词。

      例如

      1.to_words # one ,
      
      100.to_words # one hundred ,
      
      101.to_words # one hundred and one
      

      它还可以转换负数。

      【讨论】:

        【解决方案5】:

        我可以看到您要查找的内容,您不妨查看这篇 StackOverflow 帖子:Number to English Word Conversion Rails

        总结如下:

        不,你必须自己写一个函数。最接近什么的东西 你想要的是 number_to_human,但这不会将 1 转换为 One。

        以下是一些可能有用的网址:

        http://codesnippets.joyent.com/posts/show/447 http://raveendran.wordpress.com/2009/05/29/ruby-convert-number-to-english-word/ http://deveiate.org/projects/Linguistics/

        【讨论】:

          【解决方案6】:

          我不太确定,这是否适合你。方法可以这样调用。

          n2w(33123) {|i| puts i unless i.to_s.empty?}
          

          这里是方法(我没有完全测试过。我认为它可以工作到百万。代码很丑,重构的空间很大。)

          def n2w(n)
            words_hash = {0=>"zero",1=>"one",2=>"two",3=>"three",4=>"four",5=>"five",6=>"six",7=>"seven",8=>"eight",9=>"nine",
                              10=>"ten",11=>"eleven",12=>"twelve",13=>"thirteen",14=>"fourteen",15=>"fifteen",16=>"sixteen",
                               17=>"seventeen", 18=>"eighteen",19=>"nineteen",
                              20=>"twenty",30=>"thirty",40=>"forty",50=>"fifty",60=>"sixty",70=>"seventy",80=>"eighty",90=>"ninety"}
            scale = {3=>"hundred",4 =>"thousand",6=>"million",9=>"billion"}
          
            if words_hash.has_key?n
              yield words_hash[n] 
            else
              ns = n.to_s.split(//)
                while ns.size > 0      
                  if ns.size == 2
                      yield("and")
                      yield words_hash[(ns.join.to_i) - (ns.join.to_i)%10]            
                      ns.shift
                  end
                  if ns.size > 4
                    yield(words_hash[(ns[0,2].join.to_i) - (ns[0,2].join.to_i) % 10])
                  else
                    yield(words_hash[ns[0].to_i]) 
                  end
                  yield(scale[ns.size])
                  ns.shift
                end
              end
          end
          

          【讨论】:

            【解决方案7】:
            def subhundred number
            
              ones = %w{zero one two three four five six seven eight nine
                        ten eleven twelve thirteen fourteen fifteen
                        sixteen seventeen eighteen nineteen}
            
              tens = %w{zero ten twenty thirty **forty** fifty sixty seventy eighty ninety}
            
              subhundred = number % 100
            
              return [ones[subhundred]] if subhundred < 20
            
              return [tens[subhundred / 10]] if subhundred % 10 == 0
            
              return [tens[subhundred / 10], ones[subhundred % 10]]
            
            end
            
            
            
            
            def subthousand number
            
              hundreds = (number % 1000) / 100
            
              tens = number % 100
            
              s = []
            
              s = subhundred(hundreds) + ["hundred"] unless hundreds == 0
            
              s = s + ["and"] unless hundreds == 0 or tens == 0
            
              s = s + [subhundred(tens)] unless tens == 0
            
            
            end
            
            
            
            
            def decimals number
            
              return [] unless number.to_s['.']
            
              digits = number.to_s.split('.')[1].split('').reverse
            
              digits = digits.drop_while {|d| d.to_i == 0} . reverse
            
              digits = digits.map {|d| subhundred d.to_i} . flatten
            
              digits.empty? ? [] : ["and cents"] + digits
            
            end
            
            
            
            
            
            def words_from_numbers number
            
              steps = [""] + %w{thousand million billion trillion quadrillion quintillion sextillion}
            
              result = []
            
              n = number.to_i
            
              steps.each do |step|
            
                x = n % 1000
            
                unit = (step == "") ? [] : [step]
            
                result = subthousand(x) + unit  + result unless x == 0
            
                n = n / 1000
            
              end
            
            
            
              result = ["zero"] if result.empty?
            
              result = result + decimals(number)
            
            
            
            
              result.join(' ').strip
            
            end
            
            
            
            
            
            
             def words_from_numbers(number)
            
                ApplicationHelper.words_from_numbers(number)
            
              end
            

            【讨论】:

              【解决方案8】:

              这个问题被问到已经有一段时间了。 Rails 现在为此内置了一些东西。 https://api.rubyonrails.org/classes/ActionView/Helpers/NumberHelper.html

              number_to_human(1234567)                                      # => "1.23 Million"
              number_to_human(1234567890)                                   # => "1.23 Billion"
              number_to_human(1234567890123)                                # => "1.23 Trillion"
              number_to_human(1234567890123456)                             # => "1.23 Quadrillion"
              number_to_human(1234567890123456789)                          # => "1230 Quadrillion"
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2019-03-27
                • 1970-01-01
                相关资源
                最近更新 更多