2009-08-24 12 views
54

私は次のコードを持っている:str.translateをUnicode文字列で動作させるにはどうすればよいですか?

import string 
def translate_non_alphanumerics(to_translate, translate_to='_'): 
    not_letters_or_digits = u'!"#%\'()*+,-./:;<=>[email protected][\]^_`{|}~' 
    translate_table = string.maketrans(not_letters_or_digits, 
             translate_to 
             *len(not_letters_or_digits)) 
    return to_translate.translate(translate_table) 

非Unicode文字列のための素晴らしい作品:

>>> translate_non_alphanumerics('<foo>!') 
'_foo__' 

しかし、Unicode文字列で失敗を:

>>> translate_non_alphanumerics(u'<foo>!') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 5, in translate_non_alphanumerics 
TypeError: character mapping must return integer, None or unicode 

私はいずれかを作ることができませんstr.translate()メソッドのPython 2.6.2 docsの「Unicodeオブジェクト」に関する段落の意味

この作業はどのようにUnicode文字列にするのですか?

+0

ここでは、 'unicode.translate()'メソッド(http://stackoverflow.com/a/11066687/4279)を使用して文字列からUnicode句読点を削除する例を示します。 – jfs

+0

'import string;実際のコードで 'not_letters_or_digits'をハードコーディングする代わりに' string.punctuation'を使用します。私はここであなたがむしろ明白になるだろう。 –

答えて

50

translateのUnicode版では、Unicodeの序数からUnicodeの序数に(ordで1文字を取り出すことができる)Unicode序数へのマッピングが必要です。文字を削除する場合は、Noneにマップします。

私はあなたに変換したいの序にすべての文字の順序をマッピングする辞書構築するためにあなたの関数を変更:

def translate_non_alphanumerics(to_translate, translate_to=u'_'): 
    not_letters_or_digits = u'!"#%\'()*+,-./:;<=>[email protected][\]^_`{|}~' 
    translate_table = dict((ord(char), translate_to) for char in not_letters_or_digits) 
    return to_translate.translate(translate_table) 

>>> translate_non_alphanumerics(u'<foo>!') 
u'_foo__' 

編集:それは変換マッピングからマッピングしなければならないことが判明しUnicode序数(ord経由)を別のUnicode序数、Unicode文字列、またはNone(削除する)のいずれかに変更します。したがって、translate_toのデフォルト値をUnicodeリテラルに変更しました。たとえば:

>>> translate_non_alphanumerics(u'<foo>!', u'bad') 
u'badfoobadbad' 
+9

ありがとうございました! (そのようなダムデザインの決定には、異なる動作をする同じ名前の関数があります。) – Sabuncu

+1

また、句読点の文字を手動で定義したくない場合は、次のようにします。あなたの 'not_letters_or_digits'には '$'がありません。 – dpb

+0

あなたの' not_letters_or_digits'には '$'がありません。そして、あなたの 'not_letters_or_digits'には '$'がありません。 '&'。 –

5

私は私の元の関数の次の組み合わせを思い付いたとMikeのUnicodeとASCII文字列で動作するバージョン:

def translate_non_alphanumerics(to_translate, translate_to=u'_'): 
    not_letters_or_digits = u'!"#%\'()*+,-./:;<=>[email protected][\]^_`{|}~' 
    if isinstance(to_translate, unicode): 
     translate_table = dict((ord(char), unicode(translate_to)) 
           for char in not_letters_or_digits) 
    else: 
     assert isinstance(to_translate, str) 
     translate_table = string.maketrans(not_letters_or_digits, 
              translate_to 
               *len(not_letters_or_digits)) 
    return to_translate.translate(translate_table) 

更新translate_toに 『強要』ユニコードのユニコードtranslate_table。ありがとうマイク。 STRとUnicodeの両方のオブジェクト上で動作します簡単なハック、 については

+0

translate_toをUnicode版のためにUnicodeに強制することをお勧めします。そうしないと、Unicode文字列を渡すと翻訳呼び出しが狂ってしまいます。 "文字列。 –

+0

これは言語の一部であるべきもののようです。 +1 – bukzor

4

)(翻訳し実行する前にUnicodeに変換テーブルを変換:

import string 
def translate_non_alphanumerics(to_translate, translate_to='_'): 
    not_letters_or_digits = u'!"#%\'()*+,-./:;<=>[email protected][\]^_`{|}~' 
    translate_table = string.maketrans(not_letters_or_digits, 
             translate_to 
             *len(not_letters_or_digits)) 
    translate_table = translate_table.decode("latin-1") 
    return to_translate.translate(translate_table) 

ここでキャッチは、それは暗黙的にすべてのstrオブジェクトに変換するということですto_translateにASCII以外の文字が含まれていると、エラーがスローされます。

0

代わりに交換する必要があるすべての文字を指定するのでそうのように、あなたも、それを他の方法で回避を表示して、代わりに、有効な文字のみを指定することができます。

import re 

def replace_non_alphanumerics(source, replacement_character='_'): 
    result = re.sub("[^_a-zA-Z0-9]", replacement_character, source) 

    return result 

これはで動作しますがユニコードと通常の文字列を使用し、型を保存します(replacement_charactersourceの両方が同じ型の場合は明らかです)。

7

このバージョンでは、相対的に他の

def trans(to_translate): 
    tabin = u'привет' 
    tabout = u'тевирп' 
    tabin = [ord(char) for char in tabin] 
    translate_table = dict(zip(tabin, tabout)) 
    return to_translate.translate(translate_table) 
0

に自分の手紙を作ることができ、私はどこのpython 2であることが分かりました。あなたは多分、これは便利です

table = {ord(s): d for s, d in zip("123", "abc")} 
print("135".translate(table)) 

を書きますのpython 3.6で

table = {ord(s): unicode(d) for s, d in zip("123", "abc")} 
print u"135".translate(table) 

を言うunicode 7は、タイプstrで、あなたはタイプとのに対し

import string 
table = string.maketrans("123", "abc") 
print "135".translate(table) 

を記述します。

関連する問題