Normalização de sequências de caracteres

December 15, 2009

Um dos motivos que diminuiram minha participação neste blog nos últimos meses foi o meu trabalho intenso no SigaSeuTime. Entre os sócios no projeto, sou o único desenvolvedor, e a lista de tarefas não para de crescer. Gostaria de contar aqui um problema simples que tive que resolver, e que pode interessar outros desenvolvedores.

No mês passado, colocamos no ar dois bots, um para o MSN e outro para o GTalk/Orkut, que podem ser utilizados como alternativa para o Twitter para receber notícias e jogos ao vivo. Os bots funcionam como usuários normais: você adiciona o dito cujo na sua lista de amigos (usando o email sigaseutime@siga.st) e passa a receber mensagens. Ao contrário do Twitter, onde cada canal representa um time (@sigaFlamengo, @sigaVasco, @sigaCorinthians, etc…), nos bots um usuário pode selecionar um ou mais times, enviando a mensagem siga <nomedotime>.

Internamente, eu mantenho duas versões de nomes para cada canal do sistema: o nome completo (Corinthians, São Paulo, Palmeiras, Santo André, Seleção Brasileira, etc..) e um slug (corinthians, saopaulo, palmeiras, santoandre, selecaobr). Pra quem não sabe, um slug pode ser definido como uma versão URL Friendly do nome: sem acentos, espaços em branco e caracteres não ASCII. Originalmente, os bots aceitavam o uso de um dos dois nomes no comando. Por exemplo, siga Santo André ou siga santoandre.

Obviamente, fomos recebendo feedbacks de usuários que não conseguiam cadastrar um time. Em geral, isto acontecia com times com nomes compostos e/ou acentos. Analisei o log e percebi que era muito comum alguém digitar siga sao paulo por exemplo. Como o cliente tem sempre razão, decidi que um algoritmo mais espertinho de leitura do nome se fazia necessário: criei então uma funcionalidade de conversão de nomes para slugs. A primeira parte foi fácil: colocar tudo em letras minúsculas, remover espaços e outros simbolos não conformes.

Faltava a parte mais importantes: converter caracteres acentuados em caracteres não acentuados. afinal, para efeito de comparação, são e sao deveriam ser equivalentes. Inicialmente pensei em criar uma tabelinha de conversão simples, mas desisti porque a chance de alguém digitar um caso não contemplado era muito grande. Fui então pesquisar na Internet, e descobri que o UNICODE já prevê esta funcionalidade, e já tem tudo mapeado. Ainda bem que existem cientistas da computação prevenidos no mundo!

Este recurso se chama Normalização (como não pensei nisso antes….), e oferece 4 formas distintas: NFD, NDC, NFKC, e NFKD. Cada uma tem suas particularidades, e aconselho a quem se interessar pelo assunto pesquisar no site do UNICODE: http://www.unicode.org/faq/normalization.html.

O essencial é entender que existe um mapeamento de caracteres compostos (por exemplo ç = c + cedilha, ou ã = a + ˜), e que existem bibliotecas em algumas linguagens que implementam este mapeamento e que podem ser utilizadas para fazer a conversão. Vou dar um exemplo em Java e em Python:

Java:

import java.text.Normalizer;
import java.text.Normalizer.Form;
Normalizer.normalize(string, Form.NFD);

Python:

from unicodedata import normalize
unicodedata.normalize(forma, string)#forma pode ser 'NFC', 'NFD', 'NFKC' ou 'NFKD'

Utilizando este recurso, eu consigo facilmente converter SANto André, Santo Andre, SANTOandre ou qualquer outra combinação para o formato que eu espero: santoandre.

tags: , , , ,
posted in Desenvolvimento by Miguel Galves

Follow comments via the RSS Feed | Leave a comment | Trackback URL

View Comments to "Normalização de sequências de caracteres"

  1. Roger Leite wrote:

    Assunto interessante Miguel! Apesar de agora parecer óbvio, nunca tinha imaginado que o unicode tivesse uma normalização especificada. Da hora!

    Aproveitando, esta parte de unicode é uma área “em aberto” no mundo Ruby, que por sinal, só tem algo “implementado” (tipo não-gambiarra) no Ruby 1.9. De qualquer maneira, se alguém quiser usar a normalização em Ruby, googlando, achei esta gem:

    http://github.com/lang/unicode_utils No rdoc desta classe http://unicode-utils.rubyforge.org/classes/UnicodeUtils.html , tem informação útil. Importante: UnicodeUtils works with Ruby 1.9.1 or later.

    Não pude testar aqui, pois teria que atualizar o ruby e deu muita preguiça.

    Flw e sucesso!

  2. Raphael Lullis wrote:

    O django já não tem um método “slugify”, não? Bem provável que faça uso do esquema que você está falando.

  3. Miguel Galves wrote:

    Provavelmente tem embutido, e provavelmente usa o esquema de normalização. Acabei pesquisando isso porque no caso do bot eu implementei em Java. Além do mais, acho que o slugify do Django não remove os -….

Leave Your Comment

blog comments powered by Disqus

Switch to our mobile site

 
Powered by Wordpress and MySQL. Theme by Shlomi Noach, openark.org