2012-10-16 6 views
13

IPython पर निम्नलिखित एक्सचेंज पर विचार शामिल हैं:पायथन: हो रही सही स्ट्रिंग की लंबाई जब यह सरोगेट जोड़े

In [1]: s = u'華袞與緼同歸' 

In [2]: len(s) 
Out[2]: 8 

सही उत्पादन 7 किया जाना चाहिए था, लेकिन इन सात चीनी अक्षरों के पांचवें एक उच्च यूनिकोड कोड है, क्योंकि -पॉइंट, यह केवल एक साधारण कोडपॉइंट की बजाय "सरोगेट जोड़ी" द्वारा यूटीएफ -8 में दर्शाया गया है, और नतीजतन पायथन सोचता है कि यह एक के बजाय दो अक्षर है।

यहां तक ​​कि अगर मैं unicodedata है, जो सही ढंग से किराए की जोड़ी देता है एक भी कोडपॉइंट (\U00026177) के रूप में उपयोग करते हैं, जब len() के लिए पारित गलत लंबाई अभी भी दिया जाता है:

In [3]: import unicodedata 

In [4]: unicodedata.normalize('NFC', s) 
Out[4]: u'\u83ef\u889e\u8207\u7dfc\U00026177\u540c\u6b78' 


In [5]: len(unicodedata.normalize('NFC', s)) 
Out[5]: 8 

के लिए अजगर recompiling की तरह कठोर कदम उठाने के बिना यूटीएफ -32, क्या इस तरह की स्थितियों में सही लंबाई पाने का एक आसान तरीका है?

मैं आईपीथन 0.13, पायथन 2.7.2, मैक ओएस 10.8.2 पर हूं।

+0

चर्चाएं [यहां] (http://stackoverflow.com/questions/9934752/platform-specific-unicode-semantics-in-python-2-7) और [यहां] (http://stackoverflow.com/ प्रश्न/6922480/कैसे-से-एक-विश्वसनीय-यूनिकोड-वर्ण-गिनती-इन-पायथन) प्रासंगिक प्रतीत होता है। – DSM

+0

@DSM: इन्हें खोदने के लिए धन्यवाद। आपका पहला लिंक यूटीएफ -32 ("चौड़ा निर्माण") के लिए संकलित पायथन दिखाता है, जिसे मैंने अपने प्रश्न में अस्वीकार कर दिया था। दूसरे में, वेबेरी द्वारा जवाब वास्तव में सही वर्णों को गिनने के लिए कोड का एक विस्तृत टुकड़ा दिखाता है। मेरा डिफ़ॉल्ट कामकाज उत्तरार्द्ध की तरह है, लेकिन मुझे उम्मीद है कि कुछ अंतर्निहित और अधिक प्रत्यक्ष मौजूद है। – brannerchinese

+0

मैं यहां अपना परिणाम पुन: पेश नहीं कर सकता (उबंटू बॉक्स, पायथन 2.7.2)। यूनिकोड के लिए आप \ u83ef \ u889e \ u8207 \ u7dfc \ U00026177 \ u540c \ u6b78 'मुझे दोनों लेन (ओं) और लेन (यूनिकोड.नोर्मलाइज (' एनएफसी ', एस) के साथ सात की लंबाई मिलती है) – Vicent

उत्तर

7

मुझे लगता है कि यह 3.3 में तय किया गया है। देखें:

http://docs.python.org/py3k/whatsnew/3.3.html
http://www.python.org/dev/peps/pep-0393/ (wstr_length के लिए खोज)

+0

हां। लेकिन 2.7 में हम स्पष्ट रूप से अपने आप पर हैं, जब तक कि हम व्यापक निर्माण का उपयोग नहीं कर रहे हैं। दुर्भाग्यवश, मैं पी 3 पर जाने से पहले कुछ समय पहले होगा। – brannerchinese

+1

मैं फरवरी में पी 3 में स्थानांतरित हुआ, और (जब मुझे एनएलटीके जैसे पुस्तकालयों द्वारा 2.7 में वापस मजबूर किया गया) छोड़कर) सरोगेट जोड़े के साथ मेरी परेशानी खत्म हो गई है। यह वास्तव में अब सबसे अच्छा समाधान है। – brannerchinese

3

आप अजगर (देखें: How does len work?) में लेन समारोह ओवरराइड कर सकते हैं और जोड़ने के एक अगर यह में बयान अतिरिक्त लंबे यूनिकोड के लिए जाँच करने के लिए।

6

मैं एक समारोह अजगर 2 पर यह करने के लिए करते हैं:

SURROGATE_PAIR = re.compile(u'[\ud800-\udbff][\udc00-\udfff]', re.UNICODE) 
def unicodeLen(s): 
    return len(SURROGATE_PAIR.sub('.', s)) 

एक भी चरित्र के साथ किराए की जोड़े की जगह से, हम 'ठीक' len कार्य करते हैं। सामान्य तारों पर, यह बहुत कुशल होना चाहिए: चूंकि पैटर्न मेल नहीं खाएगा, इसलिए मूल स्ट्रिंग को संशोधन के बिना वापस कर दिया जाएगा। यह चौड़े (32-बिट) पायथन बिल्ड पर भी काम करना चाहिए, क्योंकि सरोगेट जोड़ी एन्कोडिंग का उपयोग नहीं किया जाएगा।

+0

यह 4-बाइट यूनिकोड वर्णों के साथ काम नहीं करेगा, उदाहरण के लिए – wojcikstefan

+0

@wojcikstefan यह करना चाहिए, आप ऐसा क्यों कहते हैं? सरोगेट जोड़ी तंत्र कुछ भी एन्कोड करता है जो यूटीएफ -16 में फिट नहीं होता है; उदाहरण के लिए, डी 83 डी डीसीएए है। –

+0

मैं '1' की लंबाई लौटने के लिए एक एकल बाइसप चार (ऊपर की तरह) की अपेक्षा करता हूं, लेकिन 'यूनिकोडेलन (यू' \ U0001f4aa \ U0001f3ff ')' रिटर्न' 2'। क्या मेरी उम्मीद गलत है @ क्रिस्पी? – wojcikstefan

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