2012-12-28 48 views
2

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

回顾以前的问题,我了解到pynum2word在几种语言中只有一种方式(num - > words),但唉,而不是意大利语。

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

谢谢。

+0

如果您看一下pynum2word模块的源代码,为什么不用num2word_EN.py中的所有英文字符串替换它们的意大利语对应字符?这很冒险,但是你不必深入研究源代码就能达到预期的效果。 – stib

+0

或者西班牙语模块可能会接近意大利语。 –

回答

2

要做到从意大利转换为众多IT使用正则表达式很简单:

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的准确synonim应该不会太难,或者添加一些错误检查,以便在发现拼写错误时会引发错误。请注意这一点。

至于调试上面的代码(如果你想改变)一个建议是添加一行:

print 'token:', token, 'current result:', result 

由于for循环的第一条指令。然后看看正在做什么,你应该能够识别代码背后的“推理”,并查看bug所在的位置。

我认为对于其他转换,可以很容易地实现基于pynum2word的东西。如果你不知道意大利语,我可能会试着帮忙写。

+0

谢谢,这完美的作品!至于单词的数字,最好直接将代码添加到pynum2word中。再次感谢。 –

+0

...几乎完美。我把我认为应该是24(我不会说意大利语...)的ventiquattro,但结果是244. –

+0

严。你说得对,我现在试着解决这个问题。 – Bakuriu

相关问题