Search code examples
pythonfor-loopscriptingalphanumeric

converting digits to word in string in python


> #!/usr/bin/env python
> 
> import inflect
> 
> p = inflect.engine() 
s1 = ''
> 
>         word = 'so do 1st or do 2nd or 3rd byte 4 th so do 5th longest word 3765 word 50 but 7th'
>     list_word = list(word)
>     print (list_word)
>     
>     for(m= 0; m <list_word.len(); m++):
>            if list_word[m].isalpha():
>                    s1 += i + ''
>            elif list_word[m].isnumeric():
>                    if (list_word[m+1].isnumeric()):
>                            continue
>                    elif (list_word[m+1]+list_word[m+2] == 'st'):
>                            s1 += first + ''
>                            m += 2
>                    elif (list_word[m+1]+list_word[m+2] == 'nd'):
>                            s1 += second + ''
>                            m += 2
>                    elif (list_word[m+1]+list_word[m+2] == 'rd'):
>                            s1 += third + ''
>                            m += 2
>                    elif (list_word[m+1]+list_word[m+2] == 'th'):
>                            if (list_word[m] == '5'):
>                                  s1 += fifth + ''
>                                  m += 2
>                            else :
>                                  s1 += p.number_to_words(list_word[m]) + ''
>                                  m += 2
>                    elif (list_word[m+1].isnumeric()):
>                            continue
>                    else:
>                            s1 += p.number_to_words(list_word[m]) + ''
>            else:
>                    s1 += ' '
> 

I need to convert digits to word and make a complete string with alphabets only. But the issue is this kind of for loop can not be used in Python and i need to iterate to next to next character at some places. Can I get any suggestions regarding this, please. Or if someone can suggest any other approach.


Solution

  • Using the num2words package we can do do this to translate the whole string without any for-loops:

    import re
    import num2words
    
    def transInt(num, mode=None):
        # Changes the mode of the translation to 
        # correctly translate ordinal numbers.
        if mode:
            mode = "ordinal"
        else:
            mode = "cardinal"
    
        # translates the number to either float
        # or int, so the translation works correctly.
        if "." in num:
            num = float(num)
        else:
            num = int(num)
        return num2words.num2words(num, to=mode)
    
    def replaceInt(string):
        # Matches numbers, followed by optional ordinal-characters after it.
        return re.sub(r"(\d+\.*\d*)(st|nd|rd|th)*", lambda x: transInt(*x.groups()), string)
    
    word = 'so do 1st or do 2nd or 3rd byte 4th so do 5th longest word 3765 word 50 but 7th'
    print(word)
    print(replaceInt(word))
    

    Output:

    so do 1st or do 2nd or 3rd byte 4th so do 5th longest word 3765 word 50 but 7th
    so do first or do second or third byte fourth so do fifth longest word three thousand, seven hundred and sixty-five word fifty but seventh
    

    The important thing with the translation is that the suffix ("th" in 5th) is connected to the number. In your example you have "4 th" which will not work with my code. Or rather, it will translate 4 as four instead of fourth