Как реализовать соответствие строк в Unicode, складывая в python

У меня есть приложение, реализующее инкрементный поиск. У меня есть каталог строк юникода, который нужно сопоставить, и сопоставлять их с данной «ключевой» строкой; строка каталога является «хитом», если она содержит все символы в ключе, по порядку, и она лучше оценивается, если кластер ключей кластер в строке каталога.

В любом случае, это отлично работает и точно соответствует юникоду, так что «öst» будет соответствовать « Öst blocket» или «r öst » или «r ö d st en».

В любом случае, теперь я хочу реализовать сворачивание, поскольку есть некоторые случаи, когда нецелесообразно различать символ каталога, такой как «á» или «é», и ключевой символ «a» или «e».

Например: «Оле» должно соответствовать «Оле»,

Как лучше всего реализовать этот разворачивающий юникод в Python? Эффективность важна, поскольку мне приходится сопоставлять тысячи строк каталога с коротким заданным ключом.

Он не должен превращать его в ascii; Фактически, выходная строка алгоритма может быть unicode. Оставить персонажа лучше, чем лишить его.


Я не знаю, какой ответ принять, поскольку я использую немного обоих. Принимая декомпозицию NKFD и удаляя комбинации меток, вы почти закончите, я добавлю к ним некоторые пользовательские транслитерации. Вот модуль, который теперь выглядит: (Предупреждение, содержит символы unicode inline, так как это намного лучше редактировать.)

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

(И для фактического соответствия, если это кого-то интересует: я заранее создаю сложенные строки для всего моего каталога и поместил свернутые версии в уже имеющееся свойство псевдонимов каталога.)

5 Solutions collect form web for “Как реализовать соответствие строк в Unicode, складывая в python”

Вы можете использовать эту функцию strip_accents для удаления акцентов:

 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' 

Для моего приложения я уже обращался к этому в другом комментарии: я хочу получить результат unicode и оставить необработанные символы нетронутыми.

В этом случае правильный способ сделать это – создать объект-коллактор UCA с его силой, установленной для сравнения только с первичной силой, что, таким образом, полностью игнорирует диакритические знаки.

Я покажу, как это сделать, используя Perl в этом ответе . Первый объект-коллактор находится в нужной степени, а второй – акценты на разрывы.

Вы заметите, что никакие строки не пострадали при составлении этих сравнений: исходные данные не затронуты.

Посмотрите на это: ftp://alan.smcvt.edu/hefferon/unicode2ascii.py

Наверное, не полный, но, возможно, вы начнете.

Универсальным решением (особенно для нормализации поиска и создания пули) является модуль унифицированного кода:

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

Это порт модуля Text :: Unidecode для Perl. Это не полный, но он переводит все латинские символы, которые я мог найти, транслитерирует кириллицу, китайский и т. Д. На латынь и даже правильно обрабатывает символы полной ширины.

Вероятно, это хорошая идея просто удалить все символы, которые вы не хотите иметь в конечном выпуске, или заменить их наполнителем (например, "äßœ$" будет дешифровать до "assoe$" , поэтому вам может понадобиться снять -alphanumerics). Для символов он будет транслитерировать, но не должен (скажем, § => 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() 

Это заменило бы все не-буквенно-цифровые символы на замену фиктивных, а затем транслитерировало строку и превратило бы ее в строчный.

Как насчет этого:

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

Взято отсюда (испанский) http://python.org.ar/pyar/Recetario/NormalizarCaracteresUnicode

Interesting Posts
Python - лучший язык программирования в мире.