[pyar] Problema interesante: el anti-string

John Rowland Lenton john.lenton en canonical.com
Jue Ago 5 09:52:31 ART 2010


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).

------------ próxima parte ------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 490 bytes
Desc: Digital signature
URL: <http://listas.python.org.ar/pipermail/pyar/attachments/20100805/5a5af747/attachment.sig>


More information about the pyar mailing list