2009-08-24 14 views
54

मैं निम्नलिखित कोड:यूनिकोड तारों के साथ काम करने के लिए मैं str.translate कैसे प्राप्त करूं?

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) 

कौन सा गैर यूनिकोड स्ट्रिंग्स के लिए महान काम करता है:

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

लेकिन यूनिकोड स्ट्रिंग्स के लिए विफल रहता है:

>>> 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 में "यूनिकोड ऑब्जेक्ट्स" पर अनुच्छेद की भावना।

मैं यह काम यूनिकोड तारों के लिए कैसे कर सकता हूं?

+0

यहां एक उदाहरण है [उदाहरण के लिए 'यूनिकोड.ट्रांसलेट() 'विधि] (http://stackoverflow.com/a/11066687/4279) का उपयोग कर स्ट्रिंग से यूनिकोड विराम चिह्न को हटा देता है। – jfs

+0

बेहतर आयात 'आयात स्ट्रिंग; वास्तविक कोड में 'not_letters_or_digits' हार्डकोडिंग के बजाय string.punctuation'। मुझे लगता है कि आप यहां स्पष्ट होना चाहते हैं। –

उत्तर

50

अनुवाद के यूनिकोड संस्करण में यूनिकोड ऑर्डिनल से एक मैपिंग की आवश्यकता होती है (जिसे आप ord के साथ एक वर्ण के लिए पुनर्प्राप्त कर सकते हैं) यूनिकोड ordinals में। यदि आप वर्णों को हटाना चाहते हैं, तो आप None पर मानचित्र बनाते हैं।

मैं अपने समारोह बदल एक dict क्या आप अनुवाद करना चाहते हैं, उसके क्रमसूचक के लिए हर चरित्र की क्रमसूचक मानचित्रण के निर्माण के लिए:

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__' 

संपादित करें: ऐसा लगता है कि अनुवाद मानचित्रण से नक्शा चाहिए यूनिकोड ordinal (ord के माध्यम से) या तो एक और यूनिकोड ordinal, एक यूनिकोड स्ट्रिंग, या कोई नहीं (हटाने के लिए)। इस प्रकार मैंने यूनिकोड शाब्दिक होने के लिए translate_to के लिए डिफ़ॉल्ट मान बदल दिया है। उदाहरण के लिए:

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_non_alphanumerics(u'<foo>!', u'bad') 
u'badfoobadbad' 
+9

धन्यवाद! (इस तरह के बेवकूफ डिजाइन का निर्णय एक समान नामित फ़ंक्शन है जो अलग-अलग काम करता है।) – Sabuncu

+1

इसके अलावा, यदि आप मैन्युअल रूप से विराम चिह्नों को परिभाषित नहीं करना चाहते हैं: आयात स्ट्रिंग; string.punctuation में c के लिए translate_table = {ord (यूनिकोड (सी)) नोट: यह सभी विशेष यूनिकोड विराम चिह्नों का अनुवाद नहीं करेगा (टन हैं ...) – dpb

+0

आपके 'not_letters_or_digits' में '$' गुम है और 'एवं'। मुझे सेट या वर्णों को हार्डकोड करने के बजाय 'string.punctuation' का उपयोग करने का सुझाव दें –

5

मैं अपने मूल कार्य के निम्नलिखित संयोजन और Mike के संस्करण है कि यूनिकोड और ASCII तार के साथ काम करता के साथ आया था यूनिकोड translate_table के लिए यूनिकोड। धन्यवाद माइक।

+0

मैं सुझाव दूंगा कि आप यूनिकोड संस्करण के लिए यूनिकोड में translate_to को coerce करें, अन्यथा अनुवाद कॉल फिक्र हो जाएगा यदि आप इसे यूनिकोड स्ट्रिंग पास करते हैं, और "सामान्य "स्ट्रिंग। –

+0

ऐसा कुछ ऐसा लगता है जो भाषा का हिस्सा होना चाहिए। +1 – bukzor

4

एक सरल हैक है कि दोनों str और यूनिकोड वस्तुओं पर काम करेंगे के लिए, का अनुवाद चल() से पहले यूनिकोड अनुवाद तालिका परिवर्तित:

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 में गैर-असीसी वर्ण हैं।

0
इसके बजाय सभी पात्रों को बदलने की जरूरत है कि निर्दिष्ट करने के लिए होने के

, आप भी यह दूसरी तरह के आसपास देख सकते हैं और, बजाय, इसलिए की तरह, सिर्फ मान्य वर्ण निर्दिष्ट करें:

import re 

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

    return result 

यह साथ काम करता है यूनिकोड के साथ-साथ नियमित तार, और प्रकार को संरक्षित करता है (यदि replacement_character और source दोनों एक ही प्रकार के हैं, तो स्पष्ट रूप से)।

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

को मैंने पाया कर सकते हैं जहां कि अजगर 2 में।7, प्रकार str के साथ, आप

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

जबकि लिखते थे प्रकार के साथ unicode आप कह सकते हैं कि

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

अजगर 3.6 में आप लिखते थे

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

शायद यह उपयोगी है।

संबंधित मुद्दे

 संबंधित मुद्दे