Is there a way to convert number words to Integers?

前端 未结 16 2000
北恋
北恋 2020-11-22 06:14

I need to convert one into 1, two into 2 and so on.

Is there a way to do this with a library or a class or anythi

相关标签:
16条回答
  • 2020-11-22 06:59

    I took @recursive's logic and converted to Ruby. I've also hardcoded the lookup table so its not as cool but might help a newbie understand what is going on.

    WORDNUMS = {"zero"=> [1,0], "one"=> [1,1], "two"=> [1,2], "three"=> [1,3],
                "four"=> [1,4], "five"=> [1,5], "six"=> [1,6], "seven"=> [1,7], 
                "eight"=> [1,8], "nine"=> [1,9], "ten"=> [1,10], 
                "eleven"=> [1,11], "twelve"=> [1,12], "thirteen"=> [1,13], 
                "fourteen"=> [1,14], "fifteen"=> [1,15], "sixteen"=> [1,16], 
                "seventeen"=> [1,17], "eighteen"=> [1,18], "nineteen"=> [1,19], 
                "twenty"=> [1,20], "thirty" => [1,30], "forty" => [1,40], 
                "fifty" => [1,50], "sixty" => [1,60], "seventy" => [1,70], 
                "eighty" => [1,80], "ninety" => [1,90],
                "hundred" => [100,0], "thousand" => [1000,0], 
                "million" => [1000000, 0]}
    
    def text_2_int(string)
      numberWords = string.gsub('-', ' ').split(/ /) - %w{and}
      current = result = 0
      numberWords.each do |word|
        scale, increment = WORDNUMS[word]
        current = current * scale + increment
        if scale > 100
          result += current
          current = 0
        end
      end
      return result + current
    end
    

    I was looking to handle strings like two thousand one hundred and forty-six

    0 讨论(0)
  • 2020-11-22 07:02

    Thanks for the code snippet... saved me a lot of time!

    I needed to handle a couple extra parsing cases, such as ordinal words ("first", "second"), hyphenated words ("one-hundred"), and hyphenated ordinal words like ("fifty-seventh"), so I added a couple lines:

    def text2int(textnum, numwords={}):
        if not numwords:
            units = [
            "zero", "one", "two", "three", "four", "five", "six", "seven", "eight",
            "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen",
            "sixteen", "seventeen", "eighteen", "nineteen",
            ]
    
            tens = ["", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"]
    
            scales = ["hundred", "thousand", "million", "billion", "trillion"]
    
            numwords["and"] = (1, 0)
            for idx, word in enumerate(units):  numwords[word] = (1, idx)
            for idx, word in enumerate(tens):       numwords[word] = (1, idx * 10)
            for idx, word in enumerate(scales): numwords[word] = (10 ** (idx * 3 or 2), 0)
    
        ordinal_words = {'first':1, 'second':2, 'third':3, 'fifth':5, 'eighth':8, 'ninth':9, 'twelfth':12}
        ordinal_endings = [('ieth', 'y'), ('th', '')]
    
        textnum = textnum.replace('-', ' ')
    
        current = result = 0
        for word in textnum.split():
            if word in ordinal_words:
                scale, increment = (1, ordinal_words[word])
            else:
                for ending, replacement in ordinal_endings:
                    if word.endswith(ending):
                        word = "%s%s" % (word[:-len(ending)], replacement)
    
                if word not in numwords:
                    raise Exception("Illegal word: " + word)
    
                scale, increment = numwords[word]
    
             current = current * scale + increment
             if scale > 100:
                result += current
                current = 0
    
        return result + current`
    
    0 讨论(0)
  • 2020-11-22 07:03

    There's a ruby gem by Marc Burns that does it. I recently forked it to add support for years. You can call ruby code from python.

      require 'numbers_in_words'
      require 'numbers_in_words/duck_punch'
    
      nums = ["fifteen sixteen", "eighty five sixteen",  "nineteen ninety six",
              "one hundred and seventy nine", "thirteen hundred", "nine thousand two hundred and ninety seven"]
      nums.each {|n| p n; p n.in_numbers}
    

    results:
    "fifteen sixteen" 1516 "eighty five sixteen" 8516 "nineteen ninety six" 1996 "one hundred and seventy nine" 179 "thirteen hundred" 1300 "nine thousand two hundred and ninety seven" 9297

    0 讨论(0)
  • 2020-11-22 07:03

    A quick solution is to use the inflect.py to generate a dictionary for translation.

    inflect.py has a number_to_words() function, that will turn a number (e.g. 2) to it's word form (e.g. 'two'). Unfortunately, its reverse (which would allow you to avoid the translation dictionary route) isn't offered. All the same, you can use that function to build the translation dictionary:

    >>> import inflect
    >>> p = inflect.engine()
    >>> word_to_number_mapping = {}
    >>>
    >>> for i in range(1, 100):
    ...     word_form = p.number_to_words(i)  # 1 -> 'one'
    ...     word_to_number_mapping[word_form] = i
    ...
    >>> print word_to_number_mapping['one']
    1
    >>> print word_to_number_mapping['eleven']
    11
    >>> print word_to_number_mapping['forty-three']
    43
    

    If you're willing to commit some time, it might be possible to examine inflect.py's inner-workings of the number_to_words() function and build your own code to do this dynamically (I haven't tried to do this).

    0 讨论(0)
提交回复
热议问题