2009-09-11 8 views
9

में फोल्डिंग द्वारा यूनिकोड स्ट्रिंग मिलान को कार्यान्वित करने के लिए मेरे पास एक वृद्धिशील खोज को लागू करने वाला एक एप्लिकेशन है। मेरे पास मिलान करने के लिए यूनिकोड तारों की एक सूची है और उन्हें किसी दिए गए "कुंजी" स्ट्रिंग से मिलान करें; एक कैटलॉग स्ट्रिंग एक "हिट" है यदि इसमें कुंजी के सभी वर्ण शामिल हैं, क्रम में, और कैटलॉग स्ट्रिंग में कुंजी वर्ण क्लस्टर होने पर यह बेहतर रैंक किया जाता है।पाइथन

वैसे भी, यह ठीक काम करता है और वास्तव में यूनिकोड से मेल खाता है, ताकि "Ost" "Ost Blocket" या "आर Ost" या "आर öसेंट एन" से मेल खाएगी।

वैसे भी, अब मैं फोल्डिंग को कार्यान्वित करना चाहता हूं, क्योंकि कुछ ऐसे मामले हैं जहां कैटलॉग कैरेक्टर जैसे "á" या "é" और मुख्य वर्ण "ए" या "ई" के बीच अंतर करना उपयोगी नहीं है।

उदाहरण के लिए: "ओले" "Olé"

से मेल खाना चाहिए मैं कैसे सबसे अच्छा अजगर में इस यूनिकोड-तह मिलान लागू करते हैं? दक्षता महत्वपूर्ण है क्योंकि मुझे छोटी, दिए गए कुंजी पर हजारों कैटलॉग तारों से मेल खाना पड़ेगा।

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


मुझे नहीं पता कि कौन सा जवाब स्वीकार करना है, क्योंकि मैं दोनों का थोड़ा सा उपयोग करता हूं। एनकेएफडी अपघटन को लेना और संयोजन अंकों को हटाने का लगभग पूरा तरीका है, मैं केवल कुछ कस्टम लिप्यंतरण जोड़ता हूं। यहाँ मॉड्यूल है, क्योंकि यह अब दिखता है: (चेतावनी, यूनिकोड वर्ण इनलाइन, शामिल हैं के बाद से यह बहुत अच्छा है कि जिस तरह से संपादित करने के लिए।)

# -*- encoding: UTF-8 -*- 

import unicodedata 
from unicodedata import normalize, category 

def _folditems(): 
    _folding_table = { 
     # general non-decomposing characters 
     # FIXME: This is not complete 
     u"ł" : u"l", 
     u"œ" : u"oe", 
     u"ð" : u"d", 
     u"þ" : u"th", 
     u"ß" : u"ss", 
     # germano-scandinavic canonical transliterations 
     u"ü" : u"ue", 
     u"å" : u"aa", 
     u"ä" : u"ae", 
     u"æ" : u"ae", 
     u"ö" : u"oe", 
     u"ø" : u"oe", 
    } 

    for c, rep in _folding_table.iteritems(): 
     yield (ord(c.upper()), rep.title()) 
     yield (ord(c), rep) 

folding_table = dict(_folditems()) 

def tofolded(ustr): 
    u"""Fold @ustr 

    Return a unicode str where composed characters are replaced by 
    their base, and extended latin characters are replaced by 
    similar basic latin characters. 

    >>> tofolded(u"Wyłącz") 
    u'Wylacz' 
    >>> tofolded(u"naïveté") 
    u'naivete' 

    Characters from other scripts are not transliterated. 

    >>> tofolded(u"Ἑλλάς") == u'Ελλας' 
    True 

    (These doctests pass, but should they fail, they fail hard) 
    """ 
    srcstr = normalize("NFKD", ustr.translate(folding_table)) 
    return u"".join(c for c in srcstr if category(c) != 'Mn') 

if __name__ == '__main__': 
    import doctest 
    doctest.testmod() 

(और, वास्तविक मिलान के लिए करता है, तो है कि किसी को दिलचस्पी: मैं मुड़ा का निर्माण मेरे सभी सूची के लिए तार पहले से है, और पहले से ही उपलब्ध सूची वस्तु उर्फ ​​संपत्ति में मुड़ा हुआ संस्करणों डाल)

+0

यह वास्तव में अच्छा है, और शायद ऑटो-पूर्ण व्यक्ति नामों के लिए बेहद उपयोगी होगा, क्योंकि ज्यादातर लोग नामों की खोज करते समय उच्चारण शुरू करने के लिए परेशान नहीं होंगे। मैं जावा में कुछ ऐसा करने के तरीके पर शोध कर रहा हूं। ऐसा लगता है कि कुछ मामलों को संभाला जा सकता है: http://java.sun.com/javase/6/docs/api/java/text/Collator.html। –

+0

हाँ। ध्यान दें कि आप उपरोक्त विशेष-केस तालिका से 'ü, å, ä, ö' छोड़ना चाहेंगे, यदि आप चाहते हैं कि वे केवल उच्चारण-पट्टी हो जाएं। उन डीफटोंग विस्तार जो मैं अपने पीओवी से चाहता था (मेरी भाषा को और अधिक सही ढंग से खराब कर रहा था); ऐसी सभी चीजों के लिए अन्य भाषाओं में दुर्भाग्यपूर्ण अपवाद हैं (उदाहरण के लिए स्पेनिश ü)। – u0b34a0f6ae

उत्तर

5

आप thisstrip_accents समारोह का उपयोग कर सकते लहजे दूर करने के लिए:

http://pypi.python.org/pypi/Unidecode

यह है:

def strip_accents(s): 
    return ''.join((c for c in unicodedata.normalize('NFD', unicode(s)) if unicodedata.category(c) != 'Mn')) 

>>> strip_accents(u'Östblocket') 
'Ostblocket' 
+0

यह स्ट्रिंग में अनचाहे वर्ण छोड़ देता है, उन्हें अलग करने के बजाय, जो अच्छा है। 'Dwwięk -> Dzwiek' लेकिन 'Wyłącz -> Wyłacz'; तो मैं उस – u0b34a0f6ae

+0

के शीर्ष पर विशेष मामलों को जोड़ सकता हूं, मैं इस जवाब को स्वीकार करता हूं क्योंकि सामान्यीकरण को फ़िल्टर करना लगभग सभी तरह से जाता है। मैं जो उपयोग करता हूं उसके लिए अद्यतन प्रश्न देखें। – u0b34a0f6ae

+1

हालांकि, ध्यान दें कि आप एनएफ ** के ** डी फ़िल्टर करना चाहते हैं; यह सख्त समकक्षता के बिना एक अपघटन है, उदाहरण के लिए सबस्क्रिप्ट वर्णों को सादा अंकों में परिवर्तित कर दिया जाता है। – u0b34a0f6ae

1

इस पर एक नज़र डालें:। ftp://alan.smcvt.edu/hefferon/unicode2ascii.py

शायद पूरा नहीं हुआ है, लेकिन मिल सकता है आप शुरू कर दिया।

+0

लिपि अच्छी प्रेरणा है, लेकिन मैं वास्तव में इसे शुद्ध ascii (अब और) में बदलना नहीं चाहता। अब मैं जो उपयोग करता हूं उसके लिए अद्यतन प्रश्न देखें। – u0b34a0f6ae

1

एक सामान्य प्रयोजन समाधान (विशेष रूप से खोज सामान्यीकरण और पैदा मल के लिए) unidecode मॉड्यूल है पर्ल के लिए पाठ :: यूनिडोड मॉड्यूल का एक बंदरगाह। यह पूरा नहीं हुआ है, लेकिन यह लैटिन-व्युत्पन्न पात्रों का अनुवाद करता है जो मुझे मिल सकता है, लैटिन में सिरिलिक, चीनी, आदि का अनुवाद करता है और यहां तक ​​कि पूर्ण-चौड़ाई वाले वर्णों को सही तरीके से संभालता है।

यह शायद एक अच्छा विचार है बस सभी पात्रों आप अंतिम आउटपुट में है या उन्हें एक पूरक के साथ बदलने के लिए नहीं करना चाहती पट्टी है (उदाहरण के लिए "äßœ$""assoe$" को unidecoded किया जाएगा, ताकि आप गैर अक्षर या अंक पट्टी करना चाह सकते हैं)।पात्रों के लिए यह अनुवाद कर लेकिन जाएगा चाहिए नहीं (जैसे कि, § =>SS और =>EU) आप इनपुट को साफ करने की जरूरत है:

input_str = u'äßœ$' 
input_str = u''.join([ch if ch.isalnum() else u'-' for ch in input_str]) 
input_str = str(unidecode(input_str)).lower() 

यह एक डमी प्रतिस्थापन के साथ सभी गैर अक्षरांकीय अक्षर की जगह लेंगे और फिर स्ट्रिंग को टाइप करें और इसे लोअरकेस में बदल दें।

+0

इस टिप के लिए धन्यवाद। मेरा आवेदन बहुभाषी है, और मुझे यकीन नहीं है कि मैं इसे सख्त एसीआईआई एलियासिंग में बहुत दूर टिपना चाहता हूं। मेरे वर्तमान समाधान में अलग-अलग लेकिन शांत विशेषताएं हैं, जैसे जापानी स्क्रिप्ट 'ヘ' 'ペ' से मेल खाएगी जैसे 'ए' मैच 'ä' से मेल खाएगा; डायक्रिटिक-स्ट्रिपिंग अधिक सार्वभौमिक है, हालांकि मैंने यह स्थापित नहीं किया है या नहीं (मुझे केवल पश्चिमी उपयोगकर्ताओं से प्रतिक्रिया है)। – u0b34a0f6ae

+0

@ u0b34a0f6ae - किस प्रकार की परिस्थितियों में आप 'ペ' (पीई) 'ヘ' (वह) से मेल खाना चाहते हैं ?? – simon

1

क्या इस एक के बारे में:

normalize('NFKD', unicode_string).encode('ASCII', 'ignore').lower() 

यहाँ से लिया (स्पेनिश) http://python.org.ar/pyar/Recetario/NormalizarCaracteresUnicode

+0

मेरे आवेदन के लिए, मैंने इसे पहले से ही एक अलग टिप्पणी में संबोधित किया है: मैं एक * यूनिकोड * परिणाम प्राप्त करना चाहता हूं और * अनचाहे वर्णों को छोड़कर * छोड़ना चाहता हूं। – u0b34a0f6ae

4

अपने आवेदन के लिए, मैं पहले से ही एक अलग टिप्पणी में इस को संबोधित: मैं एक यूनिकोड करना चाहते हैं परिणाम और अनचाहे वर्ण अनछुए छोड़ दें।

उस मामले में, यह करने के लिए सही तरीका अपनी ताकत केवल प्राथमिक ताकत पर तुलना करने के लिए सेट है, जो इस तरह पूरी तरह से विशेषक की उपेक्षा के साथ एक UCA कोलेटर वस्तु बनाने के लिए है।

मैं दिखाता हूं कि this answer में पर्ल का उपयोग करके इसे कैसे किया जाए। पहली कॉललेटर ऑब्जेक्ट आपको आवश्यक ताकत पर है, जबकि दूसरा टाई ब्रेकिंग के लिए उच्चारण मानता है।

आप ध्यान देंगे कि इन तुलनाओं को बनाने में कोई तार नहीं पहुंचा है: मूल डेटा छूटा हुआ है।