我有一个应用程序实现增量搜索。我有一个要匹配的unicode字符串的目录,并将它们匹配给定的“key”字符串;如果目录字符串按顺序包含关键字中的所有字符,则该目录字符串为“命中”,如果目录字符串中的关键字符集群排名更好,则该目录字符串的排名会更好。如何通过折叠python实现Unicode字符串匹配
无论如何,这工作正常,并完全匹配的Unicode,让 “OST” 将匹配 “OST blocket” 或 “R OST” 或 “R ö d ST恩”。
无论如何,现在我想要实现折叠,因为有些情况下区分诸如“á”或“é”这样的目录字符与关键字符“a”或“e”是无用的。
例如:“奥莱报”应与“奥莱报”
如何最好地实现在Python这个unicode折叠匹配?效率非常重要,因为我必须将数千个目录字符串与短的给定密钥进行匹配。
它不必把它变成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()
(而且,对于实际的匹配,如果感兴趣的人:你建造折我所有的目录字符串时事先,并把折叠版本到已经可用的目录对象的别名属性)
这真的很酷,并且可能对自动填写人名非常有用,因为大多数人在搜索名字时不会介绍重音。我正在研究如何在Java中做类似的事情。这似乎处理一些情况:http://java.sun.com/javase/6/docs/api/java/text/Collator.html。 – 2009-09-12 19:57:49
是的。请注意,如果您想让它们变得重音剥离,您可能希望在上面的特殊表格中忽略'ü,å,ä,ö'。那些双重扩展是我从我的POV中想要的(更正确地降低我的语言);其他语言中存在不幸的例外情况(例如西班牙语)。 – u0b34a0f6ae 2009-09-24 20:00:37