21

私はこのような機能を持っています:

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 文字の長さにあるようです。'۱' のようなアラビア数字は 2 文字です。これは でわかりますord()。そして、長さの問題はここから始まります:-(

4

6 に答える 6

29

すべての文字列を UTF8 に変換するunidecodeライブラリを参照してください。異なる言語で数字を入力する場合に非常に便利です。

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'
于 2018-04-25T13:47:41.927 に答える
12

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)

「テキスト」パラメーターがユニコード自体でなければならないことを試みます。

(また、このコードは、ラムダを使用していくつかの式を 1 行に結合することで短縮できますが、そうしても意味がありませんが、読みやすさが失われます)

ここまではうまくいくはずですが、私が投稿した元の回答を読んでください

-- 元の回答

したがって、変数を Unicode としてインスタンス化すると (引用符の先頭に u を追加)、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
>>> 

ところで、「maketrans」メソッドは unicode オブジェクトには存在しません (Python2 では - コメントを参照してください)。

Unicode の基本を理解することは非常に重要です。英語のみのプログラムを書いている人でさえ、26 のラテン文字のうちの 1 文字も扱わないと考えている人にとっても重要です。さまざまな文字を扱うコードを書く場合、これは非常に重要です。たまたまの場合を除いて、自分が何をしているのかを知らずにプログラムが動作することはありません。

非常に優れた記事は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 コードなど...

于 2012-08-09T12:04:40.457 に答える
8

unidecodeすべての文字をペルシャ語から英語に変換します。数字のみを変更する場合は、次のようにします。

Python3 では、このコードを使用してペルシャ語|アラビア語の数字を英語の数字に変換し、他の文字は変更しないでください。

intab='۱۲۳۴۵۶۷۸۹۰١٢٣٤٥٦٧٨٩٠'
outtab='12345678901234567890'
translation_table = str.maketrans(intab, outtab)
output_text = input_text.translate(translation_table)
于 2020-03-12T08:05:47.107 に答える
2

Unicode 文字列を使用する:

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

また、Python ファイルのエンコーディングが正しいことを確認してください。

于 2012-08-09T07:58:58.583 に答える