Как я могу улучшить этот скрипт number2words - PullRequest
3 голосов
/ 14 ноября 2008
import sys

words = {
    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'
}

tens = [
    '',
    'twenty',
    'thirty',
    'forty',
    'fifty',
    'sixty',
    'seventy',
    'eighty',
    'ninety',
]

placeholders = [
    '',
    'thousand',
    'million',
    'billion',
    'trillion',
    'quadrillion'
]

# segMag = segment magnitude (starting at 1)
def convertTrio(number):
    return ' '.join([words[int(number[0])],  'hundred',  convertDuo(number[1:3])]) # convertDuo(number[1:3])


def convertDuo(number):
    #if teens or less
    if int(number[0]) == 1:
        return words[int(number)]
    #twenty-five
    else:
        return tens[int(number[0]) - 1] + '-' + words[int(number[1])]


if __name__ == "__main__":

    string = []
    numeralSegments = []
    numeral = sys.argv[1]

    if int(numeral) < 100:
        print convertDuo(numeral)
    else:

        # split number into lists, grouped in threes
        for i in range (0, len(numeral), 3):
            numeralSegments.append(numeral[i:i+3])

        numeralSegments.reverse()

        # for every segment, convert to trio word and append thousand, million, etc depending on magnitude
        for i in range (len(numeralSegments)):
            string.append(convertTrio(numeralSegments[i]) + ' ' + placeholders[i])

        # reverse the list of strings before concatenating to commas
        string.reverse()        
        print ', '.join(string)

Предупреждение : я начинающий питон. Я знаю, что, вероятно, есть во много раз более эффективные способы ведения дел. Буду признателен за любые указания на них.

Редактировать : Код в настоящее время работает только для чисел, число цифр которых кратно трем. Буду признателен за предложение об элегантном способе исправить это. Спасибо.

Ответы [ 6 ]

3 голосов
/ 14 ноября 2008

На ум приходят два улучшения:

  • 40 пишется "сорок", а не "сорок"
  • вашей программе нужны юнит-тесты

Посмотрите на модули Python doctest и unittest .

2 голосов
/ 14 ноября 2008

Вместо нарезки цифр используйте модульную арифметику для разделения единиц. Эта функция преобразует число меньше 100, используя данные структуры данных.

def convert(n):
    q, r = divmod(n, 10)
    if q < 2:
        return words[n]
    result = tens[q-1] # offset because tens is missing first null value
    if r:
        result += '-' + words[r]
    return result

Затем используйте преобразование рекурсивно для поддержки больших чисел, например, начните с divmod (n, 100) и т. Д.

2 голосов
/ 14 ноября 2008

Нельзя группировать цифры в «сегменты», идущие слева направо. range(0,len(),3) не сработает. Вам придется написать тот же алгоритм для вставки разделителей цифр. Вы начинаете справа, отбирая сегменты цифр.

То, что осталось (слева, понятно?), Будет состоять из 1, 2 или 3 цифр. У вас есть convertTrio и convertDuo, которые обрабатывают 3 и 2 цифры соответственно. Где-то там есть функция преобразования одной цифры (ее не видно).

Если это не домашнее задание, вот подходящий алгоритм кластеризации цифр

def segment( n ):
   segList= []
   while len(n) > 3:
       segList.insert( 0, n[-3:] )
       n= n[:-3]
   segList.insert( 0, n )
   return segList

Редактировать

Чтобы быть более Pythonic, упакуйте его как аккуратный, многократно используемый модуль. Материал внутри if __name__ == "__main__" делает две вещи, которые должны быть отделены.

Ваш синтаксический анализ командной строки (все, что связано с sys.argv - это одно. Фактическая функция «преобразования числа» - это совсем другое. Вы хотите выглядеть больше так.

if __name__ == "__main__":
    import sys
    for number in sys.argv[1:]:
        print number2string( number )

Затем ваша функция number2string становится легко используемой частью этого модуля.

1 голос
/ 14 ноября 2008

Может быть Числа и множественные слова в качестве разговорного английского помогут немного. Немного устаревший - 4 мая 2005 года.

0 голосов
/ 10 июля 2010

В случае, если кто-то читает это, ищет скрипт для цифр в слова, взгляните на inflect.py

import inflect
p = inflect.engine()
p.numwords(123456789)

дает

'one hundred and twenty-three million, four hundred and fifty-six thousand, seven hundred and eighty-nine'
0 голосов
/ 14 ноября 2008

Проверьте источник для Number :: Spell Perl-модуль. Он короткий и может быть легко перенесен на Python (если это еще не сделано).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...