Programación


8
Feb 10

Unicode y expresiones regulares (en PHP)

Le llega el momento a todo programador no anglo-parlante de enfrentarse a la difícil tarea de escribir una expresión regular que acepte tildes, cedillas y virgulillas. Difícil porque las expresiones regulares fueron creadas, como tantas otras herramientas, cuando ASCII era la única codificación existente y por lo tanto funciona con un numero de caracteres muy limitado para el mundo internacionalizado de hoy en día. Asumamos que queremos limpiar una cadena de texto quitando todo lo que no sean caracteres alfanuméricos. La respuesta obvia sería:

preg_replace('/[\w]/ui', '', $input);

Pero \w realmente equivale a [a-z0-9_] y no nos vale. Aunque en teoría la documentación de php dice que en algunos locales \w inclute letras acentuadas yo no he conseguido que pille las del español. La siguiente respuesta común es esta:

preg_replace ('/[a-z0-9áéíóúç]/ui', '', $input);

Pero esto no sólo es una guarrada enorme sino que tampoco servirá cuando querramos añadir soporte para más idiomas y al final terminaremos con una cadena de proporciones épicas intentando incluir todas la variantes de caracteres acentuados de todos los idiomas, por no hablar de todos los alfabetos.

Aunque no lo parezca existe una solución elegante y simple. Resulta que la codificación Unicode asigna una serie de propiedades a todos los caracteres, desde algunos tan obvios como si un caracter es alfabético, si es mayúscula o minúscula o si es un número hasta otros más extraños como si tiene forma cuadrada o es de uso histórico. El que a nosotros nos interesa en este caso es la propiedad alfabética. Como podéis ver no solo aparecen listadas todas las letras normales sino que también aparecen todas las letras acentuadas habidas y por haber.

Por suerte la extensión PCRE de PHP nos deja utilizar una selección limitada (pero suficiente) de propiedades Unicode en nuestras expresiones regulares combinando el caracter de control \p con el identificador de la propieda que queramos, en este caso L.

preg_replace ('/[\pL0-9]/ui', '', $input);

Hay que tener en cuenta que utilizar las propiedades unicode en una expresión regular es significantemente más lento que utilizar rangos normales, con lo cual no es recomendable usarlas para operaciones habituales o que se repitan mucho.


15
Jun 09

Mi problema con las listas de correo

Fíjense en el siguiente intercambio de correos:

  1. Pavel hace una pregunta
  2. Jose responde con un enlace a la documentación de la función en cuestión, junto con una explicación de lo que debe hacer
  3. Alexis responde con un ejemplo
  4. Carlos responde, al día siguiente exactamente lo mismo que lo que ha dicho Alexis hace unas meras horas.
  5. Manuel contesta con lo mismo que los dos que han contestado antes
  6. Y finalmente, Antonio se une a la fiesta, tres días después contestando con… lo mismo que los últimos tres.

¿Tan faltos de amor están estos tres perdedores que se ven llamados a contestar de manera repetida y sin originalidad a una pregunta tan insulsa y obvia como esta? No es la primera vez, ni será la última, que alguien hace una pregunta de respuesta simple y se abalanzan los que quieren poder fardar de que contestan preguntas en la lista de correo de Python.

Por cierto, la pregunta en cuestión es un ejemplo perfecto de cargo cult programming: cuando alguien copia y pega código sin saber bien como funciona, otro clásico infaltable de las listas de correo.


17
Oct 08

Cursores con MySQLdb en Python

Resulta que MySQLdb tiene la fea manía de devolver los resultados en una tupla (igual que PHP en realidad), en vez de devolver un dict que tiene más sentido. Esto pasa porque así se comporta el cursor que db.cursor() devuelve por defecto. Afortunadamente hay más cursores disponibles, entre ellos el DictCursor, pero yo siempre me olvido de como usarlos. Así que me anoto esto aquí para recordarlo.

Se puede hacer de dos maneras, una es por cursor individual:

import MySQLdb
db = MySQLdb.connect(...)
cursor = db.cursor(cursorclass=MySQLdb.cursors.DictCursor)

O se puede cambiar el tipo de cursor que db.cursor() devuelve por defecto:

import MySQLdb
db = MySQLdb.connect(...)
db.cursorclass = MySQLdb.cursors.DictCursor
cursor = db.cursor()

9
Sep 08

10 reglas básicas de PHP

Quiero que todo el mundo lea esto: 10 Principles of the PHP Masters. Especialmente los puntos 1 y 3.

Y presten atención que esto cae en el examén.


21
Mar 08

RSS de segunda mano

Llevo un par de días pensando en comprar un móvil nuevo. Actualmente tengo un Nokia 6230 en un estado deplorable y aunque me gusta mucho por su forma, tamaño ni demasiado pequeño ni grande y funcionalidad adecuada creo que es hora de invertir en uno nuevo.

He visto que una compañera de trabajo tiene un Nokia E60 y me ha gustado mucho. Tiene una pantalla grande, con una resolución bastante alta, corre Symbian (importante para probar Android en el futuro cercano) y tiene soporte para Wifi.

El punto es que estaba mirando si había alguno en segunda mano y aunque encontré algunos en Madrid no eran recientes y ya se habían vendido. Quise encontrar alguna manera de hacer que me avisase cuando hubiesen resultados nuevos pero no pude encontrar ni un mísero feed RSS.

Así que hice el mío. Hay una versión online y un modulo de Python para los que quieran instalarlo en su propio ordenador cuando inevitablemente los de segunda mano bloqueen la IP de mi servidor.


27
Feb 08

Project Euler

Hace un par de semanas descubrí un sitio llamado Project Euler y lo guarde en mi cuenta de del.icio.us, pero no fue hasta hace unos días que volví a tropezar con el sitio y me puse a investigar.

La idea del sitio es la siguiente, traduzco la introducción:

El proyecto Euler es una serie de desafíos matemáticos/informáticos que requieren más que un simple conocimiento matemático para resolver. A pesar de que las matemáticas ayudan a conseguir métodos elegantes y eficientes, muchos problemas requieren del uso de un ordenador y un conocimiento de programación para resolverlos.

El concepto es bastante simple: hay una serie de problemas y cada problema tiene una solución numérica única. Cada problema tiene una cajita donde se pone el resultado conseguido. Si es incorrecto el sitio nos lo dice, pero si es correcto el sitio marca el problema como completado y nos da acceso al hilo del foro correspondiente al problema. El foro permite discutir el problema y las soluciones empleadas y por lo general es bastante interesante la primera página. Después de la primera página la calidad de las entradas disminuye exponencialmente hasta que solo postean los que para calcular el numero primo X calculan todos los primos del 1 al 1.000.000, los meten en un array y cogen el indice correspondiente. Y además van, pegan el código y ponen un comentario en plan Tarda 20 minutos y consume 1.5GB de memoria. Un poco lento pero a mi me funciona.

Resulta interesante resolver los problemas especialmente si te tomas el trabajo de evitar las soluciones brute force. Ayuda a pasar el rato cuando no tienes nada que hacer o incluso para practicar programar con papel y lápiz en el Metro de camino o volviendo del trabajo. Como el método o lenguaje que uses para resolver el problema es completamente irrelevante a la hora de presentar el resultado siempre puedes atreverte con algún lenguaje esotérico. En los foros he visto soluciones escritas en J, Befunge, Assembly o incluso (válgame dios!) Visual Basic.

Yo ya voy por el nueve, y vos?