2010-09-27 6 views
6

मेरे पास स्ट्रिंग्स हैं जो बहुभाषी दोनों भाषाओं में शामिल हैं जो व्हाइटस्पेस शब्द शब्द विभाजक (अंग्रेजी, फ्रेंच, आदि) और भाषाओं (चीनी, जापानी, कोरियाई) के रूप में उपयोग करती हैं।पायथन: बहुभाषी (जैसे चीनी और अंग्रेजी) तारों पर इस "हाइब्रिड" विभाजन() को करने का कोई तरीका?

इस तरह के एक स्ट्रिंग को देखते हुए, मैं विभाजक के रूप में खाली स्थान के का उपयोग कर शब्दों में अंग्रेजी/फ्रेंच/आदि हिस्सा अलग करने के लिए, और अलग-अलग पात्रों में चीनी/जापानी/कोरियाई हिस्सा अलग करना चाहते हैं।

और मैं उन सभी अलग-अलग घटकों को एक सूची में रखना चाहता हूं।

केस 1: अंग्रेज़ी-केवल स्ट्रिंग

कुछ उदाहरण शायद यह स्पष्ट हो जाएगा। मैं चीनी अक्षरों की एक सूची में स्ट्रिंग बदल सकते हैं

>>> list(u"我爱蟒蛇") 
[u'\u6211', u'\u7231', u'\u87d2', u'\u86c7'] 

इस मामले में: इस मामले आसान है:

>>> "I love Python".split() 
['I', 'love', 'Python'] 

केस 2: चीनी केवल स्ट्रिंग। लेकिन सूची के भीतर मैं यूनिकोड अभ्यावेदन हो रही है:

[u'\u6211', u'\u7231', u'\u87d2', u'\u86c7'] 

मैं इसे कैसे यूनिकोड के बजाय वास्तविक पात्रों को प्रदर्शित करने के मिलता है? कुछ ऐसा:

['我', '爱', '蟒', '蛇'] 

??

केस 3: के अंग्रेजी & चीनी का मिश्रण:

मैं एक इनपुट स्ट्रिंग जैसे

"我爱Python" 

चालू करना चाहते हैं और यह इस प्रकार की सूची में बदल जाता है:

['我', '爱', 'Python'] 

क्या ऐसा कुछ करना संभव है?

+0

दुर्भाग्य से, वहाँ अजगर के वर्तमान में एक misfeature है 're' मॉड्यूल जो शून्य-लंबाई वाले मैचों पर विभाजित करने के लिए' re.split() 'को रोकता है: http://stackoverflow.com/questions/2713060/why-doesnt-pythons-re-split-split-on-zero-length -मैच - इसलिए आप सीधे इसके लिए पायथन में नियमित अभिव्यक्तियों का उपयोग नहीं कर सकते हैं। –

+1

कोरियाई शब्द पृथक्करण के लिए व्हाइटस्पेस का उपयोग करता है। – Leovt

उत्तर

3

मैंने सोचा कि मैं रेगेक्स दृष्टिकोण भी दिखाऊंगा। यह मेरे लिए सही नहीं लगता है, लेकिन यह ज्यादातर इसलिए है क्योंकि मैंने देखा है कि सभी भाषा-विशिष्ट i18n विषमताएं मुझे चिंतित करती हैं कि नियमित अभिव्यक्ति उन सभी के लिए पर्याप्त लचीली नहीं हो सकती है - लेकिन आपको किसी की भी आवश्यकता नहीं है उसका। (दूसरे शब्दों में - overdesign।)

# -*- coding: utf-8 -*- 
import re 
def group_words(s): 
    regex = [] 

    # Match a whole word: 
    regex += [ur'\w+'] 

    # Match a single CJK character: 
    regex += [ur'[\u4e00-\ufaff]'] 

    # Match one of anything else, except for spaces: 
    regex += [ur'[^\s]'] 

    regex = "|".join(regex) 
    r = re.compile(regex) 

    return r.findall(s) 

if __name__ == "__main__": 
    print group_words(u"Testing English text") 
    print group_words(u"我爱蟒蛇") 
    print group_words(u"Testing English text我爱蟒蛇") 

अभ्यास में, आप शायद ही एक बार regex संकलन, प्रत्येक कॉल पर नहीं करना चाहता था। फिर, चरित्र समूह के विवरण भरना आपके ऊपर है।

+0

@Glenn Maynard। आपका बहुत बहुत धन्यवाद। यह ठीक वैसा ही है जैसा मुझे चाहिए। क्या आप मुझे विभिन्न भाषाओं के लिए यूनिकोड "रेंज" को देखने के लिए पॉइंटर्स दे सकते हैं? – Continuation

+0

वास्तव में नहीं। पात्र भाषा द्वारा अच्छी तरह से समूह नहीं करते हैं; आप शायद मुख्य रूप से पर्याप्त श्रेणियों को सीधे चुन सकते हैं। –

+0

-1 @ ग्लेन मेनार्ड: "सी" लोकेल में, यह गैर-ASCII गैर-सीजेके वर्णमाला जैसे विफल रहता है उदा। फ्रांसीसी [ओपी आवश्यकता], जर्मन, रूसी - 'यू "म्यूनचेन" '->' [यूएम ', यू' \ xfc ', u'chen']' में पाया गया है। दुर्भाग्यवश इसे 're.UNICODE' ध्वज का उपयोग करके ठीक किया जा सकता है लेकिन इससे अधिकांश सीजेके वर्ण (श्रेणी' लो') से मेल खाता है। –

2

एक सूची स्वरूपण अपने घटकों के repr दिखाता है। यदि आप बचने के बजाए स्वाभाविक रूप से तारों को देखना चाहते हैं, तो आपको इसे स्वयं प्रारूपित करने की आवश्यकता होगी। (reprनहीं इन पात्रों से बचने की जानी चाहिए; repr(u'我')"u'我'", नहीं "u'\\u6211' लौटना चाहिए जाहिर है इस अजगर 3 में होता है;। केवल 2.x अंग्रेजी केन्द्रित यूनिकोड स्ट्रिंग्स के लिए भागने के साथ फंस गया है।)

एक बुनियादी एल्गोरिदम आप का उपयोग कर सकते हैं प्रत्येक चरित्र के लिए एक चरित्र वर्ग असाइन करना, फिर वर्ग द्वारा अक्षरों को समूहीकृत करना। स्टार्टर कोड नीचे है।

मैं इस के लिए एक doctest का उपयोग नहीं किया है क्योंकि मैं कुछ अजीब एन्कोडिंग मुद्दों है कि मैं (क्षेत्र से बाहर) इस पर गौर नहीं करना चाहते मारा। आपको एक सही समूह कार्य को लागू करने की आवश्यकता होगी।

ध्यान दें कि यदि आप शब्द रैपिंग के लिए इस का उपयोग कर रहे हैं, वहाँ अन्य प्रति-भाषा विचार हैं। उदाहरण के लिए, आप नॉन-ब्रेकिंग रिक्त स्थान पर तोड़ने के लिए नहीं करना चाहते हैं; आप हाइफ़न पर तोड़ना चाहते हैं; जापानी के लिए आप अलग विभाजित करने के लिए नहीं करना चाहती き ゅ; और इसी तरह।

# -*- coding: utf-8 -*- 
import itertools, unicodedata 

def group_words(s): 
    # This is a closure for key(), encapsulated in an array to work around 
    # 2.x's lack of the nonlocal keyword. 
    sequence = [0x10000000] 

    def key(part): 
     val = ord(part) 
     if part.isspace(): 
      return 0 

     # This is incorrect, but serves this example; finding a more 
     # accurate categorization of characters is up to the user. 
     asian = unicodedata.category(part) == "Lo" 
     if asian: 
      # Never group asian characters, by returning a unique value for each one. 
      sequence[0] += 1 
      return sequence[0] 

     return 2 

    result = [] 
    for key, group in itertools.groupby(s, key): 
     # Discard groups of whitespace. 
     if key == 0: 
      continue 

     str = "".join(group) 
     result.append(str) 

    return result 

if __name__ == "__main__": 
    print group_words(u"Testing English text") 
    print group_words(u"我爱蟒蛇") 
    print group_words(u"Testing English text我爱蟒蛇") 
0

ग्लेन समाधान संशोधित रूसी, फ्रेंच, आदि के लिए अक्षर प्रतीकों और काम छोड़ने के लिए:

def rec_group_words(): 
    regex = [] 

    # Match a whole word: 
    regex += [r'[A-za-z0-9\xc0-\xff]+'] 

    # Match a single CJK character: 
    regex += [r'[\u4e00-\ufaff]'] 

    regex = "|".join(regex) 
    return re.compile(regex) 
1

अजगर 3, यह भी संख्या अगर आप जरूरत विभाजित होता है।

def spliteKeyWord(str): 
    regex = r"[\u4e00-\ufaff]|[0-9]+|[a-zA-Z]+\'*[a-z]*" 
    matches = re.findall(regex, str, re.UNICODE) 
    return matches 

print(spliteKeyWord("Testing English text我爱Python123")) 

=> [ 'परीक्षण', 'अंग्रेजी', 'पाठ', '我', '爱', 'अजगर', '123']

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