我有一个实现增量搜索的应用程序.我有一个匹配的unicode字符串目录,并将它们与给定的"key"字符串匹配; 如果目录字符串按顺序包含键中的所有字符,则它是"命中",如果目录字符串中的关键字符集群,则排序更好.
无论如何,这工作正常,并完全匹配的Unicode,让"OST"将匹配" OST blocket"或"R OST "或"R ö d ST恩".
无论如何,现在我想实现折叠,因为在某些情况下,区分诸如"á"或"é"的目录字符和关键字符"a"或"e"是没有用的.
例如:"Ole"应匹配"Olé"
我如何在Python中最好地实现这个unicode-folding matcher?效率非常重要,因为我必须将数千个目录字符串与短的给定键匹配.
它不必将其变成ascii; 实际上,算法的输出字符串可以是unicode.留下一个角色比剥离它更好.
我不知道接受哪个答案,因为我使用了两者兼而有之.采用NKFD分解并删除组合标记几乎可以完成,我只添加了一些自定义音译.这是现在看起来的模块:(警告,包含内联的unicode字符,因为编辑这种方式更好.)
# -*- 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()
Run Code Online (Sandbox Code Playgroud)
(并且,对于实际匹配,如果任何人感兴趣:我事先为我的所有目录构造折叠字符串,并将折叠版本放入已经可用的目录对象别名属性中.)
您可以使用此 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'
Run Code Online (Sandbox Code Playgroud)