[pyar] Problema interesante: el anti-string

Roberto Alsina ralsina en netmanagers.com.ar
Jue Ago 5 10:04:14 ART 2010


On Thursday 05 August 2010 09:52:31 John Rowland Lenton wrote:
> On Wed, Aug 04, 2010 at 04:03:02PM -0300, Roberto Alsina wrote:
> > Forma más fácil del problema:
> > 
> > Dado un string S, crear una funcion f tal que  S1>S2 => f(S1) < f(S2)
> > 
> > Ahí creo que es más claro :-)
> 
> creo que ya tenés una solución, pero tengo otra (o será la misma? :)
> 
> y ambas usan el hecho de que python no ordena por colación (que
> depende del locale) sino por el ord() del unicode.
> 
> Como siempre, tratándose de unicode, tengo que meter la aclaración de
> que si estás comparando cosas, lo primero que tenés que hacer es
> normalizar. En particular, me gusta la función de normalización que
> hice para el plugin de Ubuntu One para Rhythmbox,
> 
>     SCRUBBING_RE = re.compile(r"[\W\s]+", re.UNICODE)
>     CLEANING_RE = re.compile(r"\s+", re.UNICODE)
> 
>     def normalize(a):
>         """Normalize the given string, to increase the chances of a
> match""" # rule #0 of unicode mangling: first, normalize
>         na = unicodedata.normalize('NFKD', a)
>         # then, strip everything that's not alphanumeric
>         na = re.sub(SCRUBBING_RE, "", na)
>         # \w leaves _s
>         na = na.replace("_", " ")
>         # then, unify spaces
>         na = re.sub(CLEANING_RE, " ", na).strip()
>         # finally, lowercase
>         na = na.lower()
>         # if there's anything left, go with that, otherwise rollback
>         return na if na else a
> 
> (© 2010 canonical, licenciado bajo LGPLv3, autor el que suscribe)
> 
> pero claro esto es bastante caro, y lo puedo hacer porque sé que no
> voy a tener demasiadas cosas para normalizar. Si tuviera muchas,
> habría hecho solamente el primer paso (normalización a NFKD); las
> normalizaciones que descomponen (NFKD y NFD) son buenísimas para
> nosotros, porque ordenan árbol después de az y antes de ba (en vez de
> después de zz). Las normalizaciones K llevan ¹ a 1 y º a o, que
> también es lo que queremos para ordenar.
> 
> 
> Bueno, habiendo dicho eso, una forma de hacer lo que querés sería:
> 
>     def f(s):
>         array.array('l', [-ord(i) for i in s])
> 
> y otra forma sería:
> 
>     def f(s):
>         return "".join(unichr(0x10ffff-ord(i)) for i in s)
> 
> la primera usa menos memoria (medida con sys.getsizeof). No he medido
> cuál es más rápida. 0x10ffff es el ord más alto de un unicode válido
> en pythones más o menos nuevos (no sé cuándo empezó a ser así, pero
> hace bastante) (y todavía podés compilar python para que sea más
> chico, pero nadie lo hace que yo sepa).

Listo, me convenciste :-)



More information about the pyar mailing list