2010-09-27 8 views
6

Her iki dilden oluşan sözcük dizisi (İngilizce, Fransızca, vb) ve dilleri olmayan (Çince, Japonca, Korece) dillerden oluşan dizelerim var.Python: bu "melez" bölmeyi() çok dilli (ör. Çince ve İngilizce) dizeler üzerinde gerçekleştirmenin herhangi bir yolu var mı?

Böyle bir dize verildiğinde, İngilizce/Fransızca/etc kısmını ayırıcı olarak boşluk kullanarak sözcüklere ayırmak ve Çince/Japonca/Korece parçayı ayrı karakterlere ayırmak istiyorum.

Ve bu tüm ayrılmış bileşenleri bir listeye koymak istiyorum.

Durum 1: Sadece İngilizce dize

bazı örnekler muhtemelen bu net hale getirecektir. Bu durum kolaydır:

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

Durum 2: Çin okunur dize:

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

Bu durumda ben Çince karakterler bir liste halinde dize açabilirsiniz. Ama liste içinde ben unicode temsillerini alıyorum:

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

nasıl gerçek karakterleri yerine unicode görüntülemek için alabilirim? Bir şey gibi:

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

??

Vaka 3: İngiliz & Çince bir karışımı:

ben bir giriş dizesi gibi

"我爱Python" 

açmak istiyor ve bunun gibi bir listeye haline döner:

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

Böyle bir şey yapmak mümkün mü?

+0

Maalesef Python'un akımına bir misfeature var sıfır uzunluklu eşleşmelerde bölünmek için re.split() öğesini engelleyen modül: http://stackoverflow.com/questions/2713060/why-doesnt-pythons-re-split-split-on-zero-length -matches - bu nedenle doğrudan doğruya Python'da normal ifadeleri kullanamazsınız. –

+1

Korece, sözcük ayırma için boşluk kullanır. – Leovt

cevap

3

Ayrıca, düzenli ifade yaklaşımını gösterebilirim. Bu bana doğru gelmiyor, ama bu çoğunlukla gördüğüm dile özgü tüm i18n garipliklerinin beni normal bir ifadenin hepsine yetecek kadar esnek olamayacağı konusunda endişelendiriyor olması. bunun (Başka bir deyişle - Aşırı tasarım.) Pratikte

# -*- 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我爱蟒蛇") 

, muhtemelen sadece her çağrıda bir kez regex derlemek isterdim. Yine, karakter gruplamanın özelliklerini doldurmak size kalmış.

, Fransızca, Rusça gibi alfabeler için semboller ve çalışmalarını düşmesi Glenn'de çözüm Modifiye
+0

@Glenn Maynard. Çok teşekkür ederim. Bu tam ihtiyacım olan şey. Çeşitli diller için unicode "menziline" bakmak için bana işaretçiler verebilir misiniz? – Continuation

+0

Gerçekten değil. Karakterler dil ile güzel bir şekilde gruplandırılmaz; Muhtemelen büyük aralıkları yeterince basit bir şekilde seçebilirsin. –

+0

-1 @ Glenn Maynard: "C" yerel ayarında, bu ASCII olmayan CJK alfabetiklerinde örn. Fransızca [OP gereksinimi], Almanca, Rusça - "u" München "-> [u'M ', u' \ xfc ', u'nchen']' de olduğu gibi. Ne yazık ki bu, 're.UNICODE' bayrağı kullanılarak düzeltilebilir, ancak bu \ '\ w \ çoğu CJK karakterini (' Lo 'kategorisi) eşleştirir. –

2

Bir listeyi biçimlendirmek, bileşenlerinin repr numarasını gösterir. Dizeleri kaçmak yerine doğal olarak görüntülemek istiyorsanız, kendiniz biçimlendirmeniz gerekir. (repr bu karakterleri kaçan edilmemelidir; repr(u'我')"u'我'" değil "u'\\u6211' dönmelidir Görünüşe göre bu Python 3'te oluyor;. Sadece 2.x İngilizce merkezli Unicode dizeleri kaçan baş başa kalıyor.)

Temel Kullanabileceğiniz algoritma, her karaktere bir karakter sınıfı atamak ve sonra sınıflara göre harfleri gruplamaktır. Başlangıç ​​kodu aşağıda.

Bunun için bir doctest kullanmamıştım çünkü içine bakmak istemediğim bazı garip kodlama sorunları (kapsam dışı) girdim. Doğru gruplama işlevini uygulamanız gerekecek.

Bunu, sözcük kaydırma için kullanıyorsanız, dil başına başka değerlendirmeler olduğunu unutmayın. Örneğin, kırılmayan alanlarda kırmak istemezsiniz; tire üzerinde kırmak istersiniz; Japonlar için ayrılmak istemiyorsunuz き ゅ; ve bunun gibi.

# -*- 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

: Python 3

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

, aynı zamanda gerekirse sayısını böler.

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")) 

=> [ 'Test', 'İngiliz', 'metin', '我', '爱', 'Python', '123']

İlgili konular