在python中将数字转换为意大利语,将意大利语转换为数字

在python中将数字转换为意大利语,将意大利语转换为数字,python,Python,我需要Python代码将数字转换为意大利语和意大利语 看看前面的问题,我了解到pynum2word在几种语言中都是单向的(num->words),但可惜的是,在意大利语中没有 如果Python中没有这样的代码,我不介意从Perl/Ruby/Java翻译这样的代码 谢谢。要将意大利语转换为数字,使用正则表达式非常简单: import re NUMBERS_SEQ = ( ('dieci', '10'), ('undici', '11'), ('dodici', '12'

我需要Python代码将数字转换为意大利语和意大利语

看看前面的问题,我了解到pynum2word在几种语言中都是单向的(num->words),但可惜的是,在意大利语中没有

如果Python中没有这样的代码,我不介意从Perl/Ruby/Java翻译这样的代码


谢谢。

要将意大利语转换为数字,使用正则表达式非常简单:

import re


NUMBERS_SEQ = (
    ('dieci', '10'),
    ('undici', '11'),
    ('dodici', '12'),
    ('tredici', '13'),
    ('quattordici', '14'),
    ('quindici', '15'),
    ('sedici', '16'),
    ('diciasette', '17'),
    ('diciotto', '18'),
    ('diciannove', '19'),
    ('venti', '20'),
    ('trenta', '30'),
    ('quaranta', '40'),
    ('cinquanta', '50'),
    ('sessanta', '60'),
    ('settanta', '70'),
    ('ottanta', '80'),
    ('novanta', '90'),
    ('cento', '100'),
    ('mille', '1000'), ('mila', '1000'),
    ('milione', '1000000'), ('milioni', '1000000'),
    ('miliardo', '1000000000'), ('miliardi', '1000000000'),
    ('uno', '1'), ('un', '1'),
    ('due', '2'),
    ('tre', '3'),
    ('quattro', '4'),
    ('cinque', '5'),
    ('sei', '6'),
    ('sette', '7'),
    ('otto', '8'),
    ('nove', '9'),
    )

NUMBERS = dict(NUMBERS_SEQ)

TOKEN_REGEX = re.compile('|'.join('(%s)' % num for num, val in NUMBERS_SEQ))


def normalize_text(num_repr):
    '''Return a normalized version of *num_repr* that can be passed to let2num.'''

    return num_repr.lower().translate(None, ' \t')


def let2num(num_repr):
    '''Yield the numeric representation of *num_repr*.'''

    result = ''

    for token in (tok for tok in TOKEN_REGEX.split(num_repr) if tok):
        try:
            value = NUMBERS[token]
        except KeyError:
            if token not in ('di', 'e'):
                raise ValueError('Invalid number representation: %r' % num_repr)
            continue

        if token == 'miliardi':
            result += '0'*9
        elif token in ('mila','milioni'):
            zeros = '0' * value.count('0')
            piece = result[-3:].lstrip('0')
            result = (result[:-len(piece)-len(zeros)] +
                      piece +
                      zeros)
        elif not result:
            result = value
        else:
            length = len(value)
            non_zero_values = len(value.strip('0'))
            if token in ('cento', 'milione', 'miliardo'):
                if result[-1] != '0':
                    result = (result[:-length] +
                              result[-1] +
                              '0' * value.count('0'))
                    continue
            result = (result[:-length] +
                      value.rstrip('0') +
                      result[len(result) -length + non_zero_values:])
    return add_thousand_separator(result)


def add_thousand_separator(s, sep='.'):
    '''Return the numeric string s with the thousand separator.'''

    rev_s = s[::-1]
    tokens = [rev_s[i:i+3][::-1] for i in range(0, len(s), 3)][::-1]
    return sep.join(tokens)
结果:

>>> let2num('unmilione')
'1.000.000'
>>> let2num('unmilionemilleduecento')
'1.001.200'
>>> let2num('unmilionemilleduecentotre')
'1.001.203'
>>> let2num('ventiquattro')
'24'
>>> let2num(normalize_text('Dieci milioni e CentoQuarantaTreMila miliardi di miliardi di miliardi Otto cento e quattro'))
'10.143.000.000.000.000.000.000.000.000.000.804'
>>> let2num('ventiquattromiliardicentotrentatremilionitredicimiladuecentouno')
'24.133.013.201'
请注意,您必须正确拼写数字。在上一个示例中,如果输入字符串:
“…centotrentatremilione…”
,使用(错误的)单数
milione
而不是
milioni
,则会得到:

>>> let2num('ventiquattromiliardicentotrentatremilionetredicimiladuecentouno')
'24.003.013.201'
这是不“正确的”。但实际上拼写是错误的。我相信,允许
milione
作为
milioni
的确切同义词,或者添加一些错误检查,以便在发现拼写错误时引发错误,应该不会太难。请注意这一点

作为调试上述代码的建议(如果要进行更改),请添加一行,如:

print 'token:', token, 'current result:', result
作为
for
循环的第一条指令。然后观察正在做的事情,您应该能够识别代码背后的“推理”,并查看错误所在


我认为对于另一种转换,基于
pynum2word
实现一些东西会很容易。如果你不懂意大利语,我可以试着帮你写它。

要将意大利语转换成数字,使用正则表达式非常简单:

import re


NUMBERS_SEQ = (
    ('dieci', '10'),
    ('undici', '11'),
    ('dodici', '12'),
    ('tredici', '13'),
    ('quattordici', '14'),
    ('quindici', '15'),
    ('sedici', '16'),
    ('diciasette', '17'),
    ('diciotto', '18'),
    ('diciannove', '19'),
    ('venti', '20'),
    ('trenta', '30'),
    ('quaranta', '40'),
    ('cinquanta', '50'),
    ('sessanta', '60'),
    ('settanta', '70'),
    ('ottanta', '80'),
    ('novanta', '90'),
    ('cento', '100'),
    ('mille', '1000'), ('mila', '1000'),
    ('milione', '1000000'), ('milioni', '1000000'),
    ('miliardo', '1000000000'), ('miliardi', '1000000000'),
    ('uno', '1'), ('un', '1'),
    ('due', '2'),
    ('tre', '3'),
    ('quattro', '4'),
    ('cinque', '5'),
    ('sei', '6'),
    ('sette', '7'),
    ('otto', '8'),
    ('nove', '9'),
    )

NUMBERS = dict(NUMBERS_SEQ)

TOKEN_REGEX = re.compile('|'.join('(%s)' % num for num, val in NUMBERS_SEQ))


def normalize_text(num_repr):
    '''Return a normalized version of *num_repr* that can be passed to let2num.'''

    return num_repr.lower().translate(None, ' \t')


def let2num(num_repr):
    '''Yield the numeric representation of *num_repr*.'''

    result = ''

    for token in (tok for tok in TOKEN_REGEX.split(num_repr) if tok):
        try:
            value = NUMBERS[token]
        except KeyError:
            if token not in ('di', 'e'):
                raise ValueError('Invalid number representation: %r' % num_repr)
            continue

        if token == 'miliardi':
            result += '0'*9
        elif token in ('mila','milioni'):
            zeros = '0' * value.count('0')
            piece = result[-3:].lstrip('0')
            result = (result[:-len(piece)-len(zeros)] +
                      piece +
                      zeros)
        elif not result:
            result = value
        else:
            length = len(value)
            non_zero_values = len(value.strip('0'))
            if token in ('cento', 'milione', 'miliardo'):
                if result[-1] != '0':
                    result = (result[:-length] +
                              result[-1] +
                              '0' * value.count('0'))
                    continue
            result = (result[:-length] +
                      value.rstrip('0') +
                      result[len(result) -length + non_zero_values:])
    return add_thousand_separator(result)


def add_thousand_separator(s, sep='.'):
    '''Return the numeric string s with the thousand separator.'''

    rev_s = s[::-1]
    tokens = [rev_s[i:i+3][::-1] for i in range(0, len(s), 3)][::-1]
    return sep.join(tokens)
结果:

>>> let2num('unmilione')
'1.000.000'
>>> let2num('unmilionemilleduecento')
'1.001.200'
>>> let2num('unmilionemilleduecentotre')
'1.001.203'
>>> let2num('ventiquattro')
'24'
>>> let2num(normalize_text('Dieci milioni e CentoQuarantaTreMila miliardi di miliardi di miliardi Otto cento e quattro'))
'10.143.000.000.000.000.000.000.000.000.000.804'
>>> let2num('ventiquattromiliardicentotrentatremilionitredicimiladuecentouno')
'24.133.013.201'
请注意,您必须正确拼写数字。在上一个示例中,如果输入字符串:
“…centotrentatremilione…”
,使用(错误的)单数
milione
而不是
milioni
,则会得到:

>>> let2num('ventiquattromiliardicentotrentatremilionetredicimiladuecentouno')
'24.003.013.201'
这是不“正确的”。但实际上拼写是错误的。我相信,允许
milione
作为
milioni
的确切同义词,或者添加一些错误检查,以便在发现拼写错误时引发错误,应该不会太难。请注意这一点

作为调试上述代码的建议(如果要进行更改),请添加一行,如:

print 'token:', token, 'current result:', result
作为
for
循环的第一条指令。然后观察正在做的事情,您应该能够识别代码背后的“推理”,并查看错误所在


我认为对于另一种转换,基于
pynum2word
实现一些东西会很容易。如果您不懂意大利语,我可以试着帮您编写。

如果您查看pynum2word模块的源代码,为什么不将num2word_EN.py中的所有英语字符串替换为意大利语对应字符串?这很有意思,但您不必深入研究源代码以获得所需的结果。或者西班牙语模块可能更接近意大利语。如果您查看pynum2word模块的源代码,为什么不将num2word_EN.py中的所有英语字符串替换为意大利语对应字符串?这是一个很粗糙的模块,但是你不需要深入研究源代码就可以获得想要的结果。或者西班牙语模块会更接近意大利语。谢谢,这非常有效!对于单词中的数字,最好直接将代码添加到pynum2word中。再次感谢……几乎完美。我输入了ventiquattro,我想应该是24(我不会说意大利语…),但结果是244。@PeriodicMaintenance好的,现在应该解决了。错误出现在
添加千分位符
中。现在它似乎可以正常工作了。谢谢,它工作得很好!对于单词中的数字,最好直接将代码添加到pynum2word中。再次感谢……几乎完美。我输入了ventiquattro,我想应该是24(我不会说意大利语…),但结果是244。@PeriodicMaintenance好的,现在应该解决了。错误出现在
添加千分位符
中。现在它似乎工作正常。