2009-09-05 18 views
14

मेरे पास लापरवाही लैटिन वर्णों के साथ एक यूनिकोड स्ट्रिंग है।लैटिन -1 से एसीआई

n=unicode('Wikipédia, le projet d’encyclopédie','utf-8') 

मैं इसे सादे ASCII यानी 'विकिपीडिया, le projet dencyclopedie' है, इसलिए सभी तीव्र/उच्चारण, सेडिला आदि हटा दिया जाना चाहिए

ऐसा करने के लिए सबसे तेज़ तरीका यह के रूप में, क्या है करने के लिए परिवर्तित करना चाहते हैं एक लंबे स्वत: पूर्ण ड्रॉपडाउन सूची

निष्कर्ष मिलान के लिए किया जा करने के लिए आवश्यक: एक के रूप में मेरी मापदंड है गति, Lennart की 'यूनिकोड एन्कोडिंग के लिए रजिस्टर अपनी खुद की त्रुटि हैंडलर/डिकोडिंग' सबसे अच्छा परिणाम (एलेक्स के जवाब देखें), गति देता है अधिक से अधिक सी के रूप में अंतर आगे बढ़ता है हर्स लैटिन हैं।

यहाँ अनुवाद तालिका मैं उपयोग कर रहा हूँ, यह भी संशोधित त्रुटि हैंडलर के रूप में यह

# -*- coding: utf-8 -*- 
import codecs 

""" 
This is more of visual translation also avoiding multiple char translation 
e.g. £ may be written as {pound} 
""" 
latin_dict = { 
u"¡": u"!", u"¢": u"c", u"£": u"L", u"¤": u"o", u"¥": u"Y", 
u"¦": u"|", u"§": u"S", u"¨": u"`", u"©": u"c", u"ª": u"a", 
u"«": u"<<", u"¬": u"-", u"­": u"-", u"®": u"R", u"¯": u"-", 
u"°": u"o", u"±": u"+-", u"²": u"2", u"³": u"3", u"´": u"'", 
u"µ": u"u", u"¶": u"P", u"·": u".", u"¸": u",", u"¹": u"1", 
u"º": u"o", u"»": u">>", u"¼": u"1/4", u"½": u"1/2", u"¾": u"3/4", 
u"¿": u"?", u"À": u"A", u"Á": u"A", u"Â": u"A", u"Ã": u"A", 
u"Ä": u"A", u"Å": u"A", u"Æ": u"Ae", u"Ç": u"C", u"È": u"E", 
u"É": u"E", u"Ê": u"E", u"Ë": u"E", u"Ì": u"I", u"Í": u"I", 
u"Î": u"I", u"Ï": u"I", u"Ð": u"D", u"Ñ": u"N", u"Ò": u"O", 
u"Ó": u"O", u"Ô": u"O", u"Õ": u"O", u"Ö": u"O", u"×": u"*", 
u"Ø": u"O", u"Ù": u"U", u"Ú": u"U", u"Û": u"U", u"Ü": u"U", 
u"Ý": u"Y", u"Þ": u"p", u"ß": u"b", u"à": u"a", u"á": u"a", 
u"â": u"a", u"ã": u"a", u"ä": u"a", u"å": u"a", u"æ": u"ae", 
u"ç": u"c", u"è": u"e", u"é": u"e", u"ê": u"e", u"ë": u"e", 
u"ì": u"i", u"í": u"i", u"î": u"i", u"ï": u"i", u"ð": u"d", 
u"ñ": u"n", u"ò": u"o", u"ó": u"o", u"ô": u"o", u"õ": u"o", 
u"ö": u"o", u"÷": u"/", u"ø": u"o", u"ù": u"u", u"ú": u"u", 
u"û": u"u", u"ü": u"u", u"ý": u"y", u"þ": u"p", u"ÿ": u"y", 
u"’":u"'"} 

def latin2ascii(error): 
    """ 
    error is protion of text from start to end, we just convert first 
    hence return error.start+1 instead of error.end 
    """ 
    return latin_dict[error.object[error.start]], error.start+1 

codecs.register_error('latin2ascii', latin2ascii) 

if __name__ == "__main__": 
    x = u"¼ éíñ§ÐÌëÑ » ¼ ö ® © ’" 
    print x 
    print x.encode('ascii', 'latin2ascii') 

error.end को क्यों मैं लौट error.start से संयुक्त राष्ट्र एन्कोड चार की पूरी श्रृंखला की देखभाल की जरूरत है error.start + 1:

लौटाई गई त्रुटि ऑब्जेक्ट कई वर्ण हो सकती है, और हम इनमें से केवल पहले को परिवर्तित करते हैं अगर मैं print error.start, error.end जोड़ने त्रुटि के लिए हैंडलर उत्पादन

¼ éíñ§ÐÌëÑ » ¼ ö ® © ’ 
0 1 
2 10 
3 10 
4 10 
5 10 
6 10 
7 10 
8 10 
9 10 
11 12 
13 14 
15 16 
17 18 
19 20 
21 22 
1/4 einSDIeN >> 1/4 o R c ' 
तो दूसरी पंक्ति हम 2-10 से वर्ण प्राप्त में

है, लेकिन हम परिवर्तित केवल 2 इसलिए लौट 3 जारी रखने के रूप में बिंदु, अगर हम error.end उत्पादन वापसी है

¼ éíñ§ÐÌëÑ » ¼ ö ® © ’ 
0 1 
2 10 
11 12 
13 14 
15 16 
17 18 
19 20 
21 22 
1/4 e >> 1/4 o R c ' 

जैसा कि हम देख सकते हैं कि 2-10 भाग को एक एकल द्वारा प्रतिस्थापित किया गया है। ऑफ-कोर्स एक बार में पूरी रेंज को एन्कोड करने और त्रुटि.एंड वापस करने के लिए तेज़ होगा, लेकिन प्रदर्शन उद्देश्य के लिए मैंने इसे सरल रखा है।

अधिक जानकारी के

+0

मुझे यकीन है कि आप जानते हैं, लेकिन ध्यान रखें कि उपयोगकर्ता को इन एसीआई-फीड तारों को न दिखाएं। एक शब्द का अर्थ पूरी तरह से बदल सकता है जब आप यादृच्छिक रूप से अधिक या कम अक्षरों को बदलते हैं ('ओ' में 'ओ' बनाते हैं और इसी तरह)। – unwind

+0

हाँ यह डिस्प्ले के लिए नहीं है लेकिन टाइपिंग के लिए, हमारे पास एसीआईआई अक्षरों की समस्या के साथ एक ऑन-स्क्रीन कीबोर्ड है, यह उपयोगकर्ता कैसे टाइप करेगा या नहीं, इसलिए यदि टाइप ई है, तो इसे स्ट्रिंग से मेल खाना चाहिए, ई, é, ê आदि –

+0

मैं डॉन ' 'error.end' के लिए' error.start + 1' के प्रतिस्थापन को समझ नहीं आया।क्या आप समझा सकते हैं? दोनों मेरे लिए भी काम करते प्रतीत होते हैं। – gorus

उत्तर

15

तो यहाँ तीन तरीकों, और अधिक या कम दिया जाता है या अन्य उत्तर में सुझाव इस प्रकार हैं:

# -*- coding: utf-8 -*- 
import codecs 
import unicodedata 

x = u"Wikipédia, le projet d’encyclopédie" 

xtd = {ord(u'’'): u"'", ord(u'é'): u'e', } 

def asciify(error): 
    return xtd[ord(error.object[error.start])], error.end 

codecs.register_error('asciify', asciify) 

def ae(): 
    return x.encode('ascii', 'asciify') 

def ud(): 
    return unicodedata.normalize('NFKD', x).encode('ASCII', 'ignore') 

def tr(): 
    return x.translate(xtd) 

if __name__ == '__main__': 
    print 'or:', x 
    print 'ae:', ae() 
    print 'ud:', ud() 
    print 'tr:', tr() 

मुख्य के रूप में चलाएं, यह उत्सर्जन करता है:

or: Wikipédia, le projet d’encyclopédie 
ae: Wikipedia, le projet d'encyclopedie 
ud: Wikipedia, le projet dencyclopedie 
tr: Wikipedia, le projet d'encyclopedie 

स्पष्ट रूप दिखा रहा है कि unicodedata आधारित दृष्टिकोण , जबकि इसमें अनुवाद मानचित्र xtd की आवश्यकता नहीं है, सभी स्वचालित रूप से स्वचालित रूप से स्वचालित रूप से अनुवाद नहीं कर सकते हैं (यह उच्चारण अक्षरों के लिए काम करता है लेकिन रिवर्स-एस्ट्रोफ़े के लिए नहीं), इसलिए इसे कुछ सहायक कदम भी चाहिए सौदा सौदा सौदा वें (इसमें कोई संदेह नहीं है कि अब उसका शरीर क्या है)।

प्रदर्शन भी दिलचस्प है। Mac OS X 10.5 और सिस्टम अजगर 2.5, काफी repeatably साथ अपने लैपटॉप पर:

$ python -mtimeit -s'import a' 'a.ae()' 
100000 loops, best of 3: 7.5 usec per loop 
$ python -mtimeit -s'import a' 'a.ud()' 
100000 loops, best of 3: 3.66 usec per loop 
$ python -mtimeit -s'import a' 'a.tr()' 
10000 loops, best of 3: 21.4 usec per loop 

translate आश्चर्यजनक रूप से धीमी गति से (अन्य तरीकों के सापेक्ष) है। मेरा मानना ​​है कि मुद्दा यह है कि translate मामले में हर चरित्र के लिए निर्देश देखा जाता है (और अधिकांश वहां नहीं हैं), लेकिन केवल उन कुछ वर्णों के लिए जो asciify दृष्टिकोण के साथ हैं।

संपूर्णता के लिए

तो यहाँ "व्यवस्था कड़ी कर दी-अप unicodedata" दृष्टिकोण है:

specstd = {ord(u'’'): u"'", } 
def specials(error): 
    return specstd.get(ord(error.object[error.start]), u''), error.end 
codecs.register_error('specials', specials) 

def bu(): 
    return unicodedata.normalize('NFKD', x).encode('ASCII', 'specials') 

यह सही उत्पादन देता है, लेकिन:

$ python -mtimeit -s'import a' 'a.bu()' 
100000 loops, best of 3: 10.7 usec per loop 

... गति नहीं कि सभी अच्छा किसी भी अधिक है । इसलिए, यदि गति मायने रखती है, तो इसमें xtd अनुवाद निर्देश बनाने और asciify दृष्टिकोण का उपयोग करने में परेशानी का कोई संदेह नहीं है। जब प्रति अनुवाद कुछ अतिरिक्त माइक्रोसेकंड कोई बड़ा सौदा नहीं होता है, तो शायद इसकी सुविधा के लिए bu दृष्टिकोण पर विचार करना चाहें (केवल एक अनुवाद निर्देश की आवश्यकता है, उम्मीद है कि कुछ विशेष वर्ण जो अंतर्निहित यूनिकोडेडाटा विचार के साथ सही ढंग से अनुवाद नहीं करते हैं)।

+0

सारांश और समय के लिए धन्यवाद :) –

+0

क्या नियम बनाते समय 'ord' करने के पीछे कोई कारण है और फिर अनुशासन के दौरान क्रमशः प्राप्त करना है? –

+0

@ अनाराग, जिस तरह से इस तरह के नियमों को'translate' - 'asciify' में तुरंत उपयोग करने योग्य है, उसे इसकी आवश्यकता नहीं है। सरलीकरण अपने समय को लगभग 7.5 से 7.3 उपयोगक तक घटा देता है। –

0

के लिए http://docs.python.org/library/codecs.html#codecs.register_error देखने को मापने के बिना, मैं उम्मीद होती है कि यूनिकोड तार के .translate विधि सबसे तेजी से समाधान है। हालांकि, आपको निश्चित रूप से अपना खुद का माप बनाना चाहिए।

1

Maketrans (और का अनुवाद) तो ascii में बदलने का:

intab = u'áéí' # extend as needed 
outtab = u'aei' # as well as this one 
table = maketrans(intab, outtab) 

text = translate(u"Wikipédia, le projet d’encyclopédie", table) 

try: 
    temp = unicode(text, "utf-8") 
    fixed = unicodedata.normalize('NFKD', temp).encode('ASCII', action) 
    return fixed 
except Exception, errorInfo: 
    print errorInfo 
    print "Unable to convert the Unicode characters to xml character entities" 
    raise errorInfo 

(here से)

+0

के लिए देखो लेकिन यह उन्हें एक्सएमएल चरित्र इकाइयों में परिवर्तित कर देगा। यही वह नहीं है जिसे उसने पूछा था। –

+0

मैं समाधान की पहली पंक्ति को समझ नहीं पा रहा हूं "मकेट्रान (और अनुवाद) फिर एसीआई में परिवर्तित करें:" इसकी आवश्यकता क्यों है और आप कोड में कहीं भी इसका उपयोग नहीं करते हैं? –

+0

@Lennart Regebro: फिर यह उन्हें ASCII में एन्कोड करता है। @Anurag Uniyal: वह उदा। 'ई' के साथ 'ई' जो एक सादा रूपांतरण उसके लिए नहीं करेगा। यही कारण है कि maketrans की जरूरत है। मैंने यहां कॉपी किए गए कोड स्निपेट को केवल यूनिकोड-> ASCII रूपांतरण दिखाता है। –

8

"सही" तरीका यह यूनिकोड एन्कोडिंग/डिकोडिंग के लिए अपनी खुद की त्रुटि हैंडलर रजिस्टर करने के लिए है करने के लिए, और कहा कि त्रुटि हैंडलर में नौकरी से ई और ओ के लिए ö, आदि

के प्रतिस्थापन प्रदान करते हैं ताकि जैसा:

# -*- coding: UTF-8 -*- 
import codecs 

map = {u'é': u'e', 
     u'’': u"'", 
     # ETC 
     } 

def asciify(error): 
    return map[error.object[error.start]], error.end 

codecs.register_error('asciify', asciify) 

test = u'Wikipédia, le projet d’encyclopédie' 
print test.encode('ascii', 'asciify') 

आपको आईबीएम की ICU लाइब्रेरी में कुछ भी मिल सकता है और यह पाइथन बाइंडिंग PyICU है, हालांकि, यह कम काम हो सकता है।

+0

+1: मैं बस असीमित फ़ंक्शन के लिए इनपुट पर कुछ और जांच जोड़ूंगा, लेकिन मुझे लगता है कि यह यूनिकोड एन्कोडिंग में कस्टम त्रुटि प्रबंधन के लिए भी एक बहुत तेज़ और अच्छा संदर्भ है। –

+0

मैं मानता हूं कि यह सही कार्यान्वयन है। शायद कोई सामान्य उद्देश्य के उपयोग के लिए एक पूर्ण मानचित्रण का सुझाव दे सकता है। सही जवाब के लिए –

+0

+1 लेकिन मुझे लगता है कि मैं पूरा होने के लिए एलेक्स का जवाब चुन रहा हूं और इसमें समय शामिल है। –

8

भयानक unidecode मॉड्यूल आप के लिए यह करता है:

>>> import unidecode 
>>> n = unicode('Wikipédia, le projet d’encyclopédie','utf-8') 
>>> unidecode.unidecode(n) 
"Wikipedia, le projet d'encyclopedie" 
+0

हां यह समान लेकिन व्यापक लगता है –

0

पैकेज unihandecode

यूनिकोड पाठ की US-ASCII लिप्यंतरण है।
पायथन यूनिडोड का एक बेहतर संस्करण, जो कि सीन एम। बर्क द्वारा टेक्स्ट :: यूनिडोड पर्ल मॉड्यूल का पायथन पोर्ट है।

pip install Unihandecode 

तो python

import unihandecode 
print(unihandecode.unidecode(u'Wikipédia, le projet d’encyclopédie')) 

प्रिंट Wikipedia, le projet d'encyclopedie में।

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