String.maketrans用于英语和波斯语数字

时间:2012-08-09 07:56:57

标签: python python-2.7 python-unicode

我有这样的功能:

persian_numbers = '۱۲۳۴۵۶۷۸۹۰'
english_numbers = '1234567890'
arabic_numbers  = '١٢٣٤٥٦٧٨٩٠'

english_trans   = string.maketrans(english_numbers, persian_numbers)
arabic_trans    = string.maketrans(arabic_numbers, persian_numbers)

text.translate(english_trans)
text.translate(arabic_trans)

我希望它将所有阿拉伯语和英语数字翻译成波斯语。但Python说:

english_translate = string.maketrans(english_numbers, persian_numbers)
ValueError: maketrans arguments must have same length

我尝试使用Unicode utf-8对字符串进行编码,但我总是遇到一些错误!有时问题是阿拉伯字符串而不是!你知道更好的解决方案吗?

编辑:

似乎问题是ASCII中的Unicode字符长度。像'1'这样的阿拉伯数字是两个字符 - 我发现ord()。长度问题从这里开始: - (

5 个答案:

答案 0 :(得分:11)

Unicode对象可以将这些数字(阿拉伯语和波斯语)解释为实际数字 - 无需使用字符替换来翻译它们。

编辑 - 我想出了一种使用Python2正则表达式进行替换的方法:

# coding: utf-8

import re

# Attention: while the characters for the strings bellow are 
# dislplayed indentically, inside they are represented
# by distinct unicode codepoints

persian_numbers = u'۱۲۳۴۵۶۷۸۹۰'
arabic_numbers  = u'١٢٣٤٥٦٧٨٩٠'
english_numbers = u'1234567890'


persian_regexp = u"(%s)" %  u"|".join(persian_numbers)
arabic_regexp = u"(%s)" % u"|".join(arabic_numbers)

def _sub(match_object, digits):
    return english_numbers[digits.find(match_object.group(0))]

def _sub_arabic(match_object):
    return _sub(match_object, arabic_numbers)

def _sub_persian(match_object):
    return _sub(match_object, persian_numbers)


def replace_arabic(text):
    return re.sub(arabic_regexp, _sub_arabic, text)

def replace_persian(text):
    return re.sub(arabic_regexp, _sub_persian, text)

尝试“text”参数必须是unicode本身。

(也可以缩短此代码 通过使用lambdas并在一行中组合一些表达式,但没有必要这样做,但是为了失去可读性)

它应该对你有用,但请阅读我发布的原始答案

- 原始回答

因此,如果将变量实例化为unicode(将u添加到引号char),则可以在Python中正确理解它们:

>>> persian_numbers = u'۱۲۳۴۵۶۷۸۹۰'
>>> english_numbers = u'1234567890'
>>> arabic_numbers  = u'١٢٣٤٥٦٧٨٩٠'
>>> 
>>> print int(persian_numbers)
1234567890
>>> print int(english_numbers)
1234567890
>>> print int(arabic_numbers)
1234567890
>>> persian_numbers.isdigit()
True
>>> 

顺便说一句,unicode对象不存在“maketrans”方法(在Python2中 - 参见注释)。

了解unicode的基本知识非常重要 - 对于每个人来说,即使是只写英语的人也认为他们永远不会处理26封拉丁字母中的任何字符。在编写处理不同字符的代码时,这是至关重要的 - 如果不知道你在做什么,程序就不可能工作,除非偶然。

一篇非常好的文章是http://www.joelonsoftware.com/articles/Unicode.html - 请现在阅读。 您可以记住,在阅读它时,Python允许通过使用unicode对象的“encode”方法将unicode字符转换为任何“物理”编码的字符串。

>>> arabic_numbers  = u'١٢٣٤٥٦٧٨٩٠'
>>> len(arabic_numbers)
10
>>> enc_arabic = arabic_numbers.encode("utf-8")
>>> print enc_arabic
١٢٣٤٥٦٧٨٩٠
>>> len(enc_arabic)
20
>>> int(enc_arabic)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: '\xd9\xa1\xd9\xa2\xd9\xa3\xd9\xa4\xd9\xa5\xd9\xa6\xd9\xa7\xd9\xa8\xd9\xa9\xd9\xa0'

因此,字符在“单个实体”和作为编码时的数字时都会失去意义 - 编码对象(Python 2.x中的str类型)只是字节的大小 - 在将这些字符发送到任何输出时仍然需要从程序 - 无论是控制台,GUI窗口,数据库,HTML代码等...

答案 1 :(得分:10)

请参阅unidecode库,将所有字符串转换为UTF8。在输入不同语言的数字时非常有用。

在Python 2中:

>>> from unidecode import unidecode
>>> a = unidecode(u"۰۱۲۳۴۵۶۷۸۹")
>>> a
'0123456789'
>>> unidecode(a)
'0123456789'

在Python 3中:

>>> from unidecode import unidecode
>>> a = unidecode("۰۱۲۳۴۵۶۷۸۹")
>>> a
'0123456789'
>>> unidecode(a)
'0123456789'

答案 2 :(得分:3)

unidecode将所有字​​符从波斯语转换为英语,如果只想更改数字,请遵循以下提示:

在python3中,您可以使用此代码将任何波斯语|阿拉伯数字转换为英文数字,​​同时保持其他字符不变:

intab='۱۲۳۴۵۶۷۸۹۰١٢٣٤٥٦٧٨٩٠'
outtab='12345678901234567890'
translation_table = str.maketrans(intab, outtab)
output_text = input_text.translate(translation_table)

答案 3 :(得分:1)

使用Unicode字符串:

persian_numbers = u'۱۲۳۴۵۶۷۸۹۰'
english_numbers = u'1234567890'
arabic_numbers  = u'١٢٣٤٥٦٧٨٩٠'

确保Python文件的编码正确无误。

答案 4 :(得分:0)

您可以使用persiantools软件包:

示例:

>>> from persiantools import digits

>>> digits.en_to_fa("0987654321")
'۰۹۸۷۶۵۴۳۲۱'

>>> digits.ar_to_fa("٠٩٨٧٦٥٤٣٢١")   # or digits.ar_to_fa(u"٠٩٨٧٦٥٤٣٢١")
'۰۹۸۷۶۵۴۳۲۱'