Tengo una aplicación que implementa la búsqueda incremental. Tengo un catálogo de cadenas de Unicode que se emparejarán y las uniré a una cadena de "clave" dada; una cadena de catálogo es un "acierto" si contiene todos los caracteres de la clave, en orden, y se clasifica mejor si los caracteres clave se agrupan en la cadena del catálogo.Cómo implementar la coincidencia de cadena Unicode plegando en python
De todos modos, esto funciona bien y coincide exactamente con Unicode, por lo que "öst" coincidirá con "Öst Blocket" o "r öst" o "r ö d st en".
De todos modos, ahora quiero implementar plegado, ya que hay algunos casos en los que no es útil distinguir entre un carácter de catálogo como "á" o "é" y el carácter "a" o "e".
Por ejemplo: "Ole" debe coincidir con "Olé"
¿Cómo implementar mejor este matcher Unicode-plegable en Python? La eficiencia es importante ya que tengo que unir miles de cadenas de catálogo con la clave corta dada.
No tiene que convertirlo en ascii; de hecho, la cadena de salida del algoritmo podría ser unicode. Dejar a un personaje es mejor que desnudarlo.
No sé qué respuesta aceptar, ya que uso un poco de ambos. Tomar la descomposición de NKFD y eliminar las marcas de combinación casi llega al final, solo agrego algunas transliteraciones personalizadas a eso. Aquí está el módulo como se ve ahora: (Advertencia, contiene caracteres Unicode en línea, ya que es mucho más agradable para editar esa manera.)
# -*- 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()
(Y, para el juego real, si que interesa a nadie: construyo doblé cuerdas para todo mi catálogo de antemano, y poner las versiones dobladas en la propiedad catálogo de objetos alias ya disponible)
Esto es realmente genial, y probablemente sea extremadamente útil para completar automáticamente los nombres de personas, ya que la mayoría de las personas no se molestará en introducir acentos al buscar nombres. Estoy investigando sobre cómo hacer algo similar en Java. Esto parece manejar algunos casos: http://java.sun.com/javase/6/docs/api/java/text/Collator.html. –
sí. Tenga en cuenta que es posible que desee excluir 'ü, å, ä' de la tabla de casos especiales anterior si desea que se vuelvan acentuados. Esas expansiones diphtong era lo que quería de mi POV (degradando más correctamente mi lenguaje); existen desafortunadas excepciones en otros idiomas para todas esas cosas (español, por ejemplo). – u0b34a0f6ae