Olá Pessoal, estou dando continuidade a série de tratamento de strings. Aos que já acompanharam o post passado, falei sobre a função Levenshtein e deixei a dica de que podíamos melhorar a relevância da comparação através do strlen().
Para este post falarei um pouco sobre a função strlen(). Ela já é bem conhecida e pode ser utilizada para diversas finalidades entre elas: validar a entrada em uma condição, contar se uma determinada string encontra-se no limite de caracteres (lembram do limite do twitter?) e limitação de loops.
Definindo a função strlen()
A definição não é muito complexa, porém sua aplicação pode ser feita em “N” situações o que torna este comando muito importante no trabalho com strings. O strlen() estritamente calcula o tamanho de uma string, simples assim. Se você tem uma determinada palavra “Capivara” e definir o strlen(“Capivara”), a função te retornará 8.
Colocando a mão na massa
Retornando ao código utilizado pela função Levenshtein, podemos reparar que a mesma pode te retornar sugestões nada relevante se todas as suas palavras de comparação forem completamente diferentes da palavra buscada. Em um primeiro passo, então pensei, limitando as palavras comparadas a ter um índice Levenshtein menor que uma determinada porcentagem (no exemplo defini 50%) da palavra digitada, se nenhuma delas tiver pelo menos 50% de semelhança não teremos nenhum retorno de semelhança.
Para isto fiz algumas modificações utilizando do comando strlen() ele será responsável por condicionar o tamanho máximo do índice Levenshtein e assim adicionar a palavra comparada à sugestão indicada.
<?php if($_GET){ $input = $_GET[word]; // Array de palavras $words = array('DialHost','Hospedagem','Sites','Cloud', 'Computing','Servidores','Brasil','iMasters','PHP'); // Inicio uma variável com a menor encontrada pela busca $sht = strlen(utf8_decode($input))/2; $print_word=''; // Inicio o loop de comparação das palavras foreach ($words as $word) { //Faço a comparação das ditâncias entre a palavra digita e a palavra selecionada no array. $lev = levenshtein($input, $word); // Verifico se a palavra do array é igual a palavra digitada. if ($lev == 0) { // Defino a palavra digitada como sendo a palavra final $print_word = $word; $sht = 0; //Já que a palavra exata já foi encontrada não preciso mais continuar no loop. break; } // Se a palavra do array não for exata começo a comparar se ela é mais próxima que a comparada anteriormente. if ($lev <= $sht || $sht < 0) { // Se der verdadeiro a palavra será guardada como a palavra final $print_word = $word; // E defino o valor levenshtein da palavra como o mais próximo. Este valor será utilizado nas comparações seguintes. $sht = $lev; } } ?>
A principal mudança aqui foi na linha 10 do código onde eu incio a menor entrada pela busca. Com ela estando diferente de "0" agora uma palavra para ser considerada uma sugestão válida tem que ser pelo menos 50% parecida com a palavra digitada no formulário. Por fim adiciono o html do formulário. <!DOCTYPE html> <html lang="pt-br"> <head> <title>Levenshtein</title> <meta charset="utf-8"> </head> <body> <?php echo "<div style='margin-top:50px;text-align:center;font-family:arial,sans-serif;font-size:1.6em;'>A palavra digitada foi:".$input."</div>"; if ($sht == 0) { echo "<div style='text-align:center;font-family:arial,sans-serif;font-size:1.6em;'>Encontramos a palavra exata para sua busca:".$print_word."</div>"; } else if ($print_word!='') { echo "<div style='line-height:1.7em;text-align:center;font-family:arial,sans-serif;font-size:1.6em;'>Talvez você esteja procurando por:".$print_word."</div>"; } else{ echo "<div style='line-height:1.7em;text-align:center;font-family:arial,sans-serif;font-size:1.6em;'>Não encontramos palavras que se pareçam com sua busca</div>"; } echo "<div style='margin-top:50px;text-align:center;font-family:arial,sans-serif;font-size:1.6em;'><a href='http://devel2.dialhost.com.br/Blog-SandBox/levenshtein.php' title='Fazer outra busca'>Fazer outra busca</a></div>"; } else { ?> <div style="margin-top:50px;text-align:center;font-family:arial,sans-serif;font-size:1em;"> <h1>Apenas um teste com Levenshtein</h1> <form action="levenshtein.php" method="get" accept-charset="utf-8"> <label> Digite a palavra a ser comparada<br><input style="padding:5px;font-size:1.4em;line-height:1.4em;margin-top:5px;"type="text" name="word" placeholder="ex: DialHost" value=""></label> <input type="submit" name="buscar" value="Buscar"> </form> <?php } ?> </div> </body> </html>
Acredito que, mesmo assim, não temos uma busca de relevância digna de Google. Mas, para um simples exemplo esta função pode aumentar bastante a relevância de suas sugestões ou correções. Confiram só o exemplo modificado
Erro comum
Na verdade este erro encontrei enquanto pesquisava sobre o assunto e só vale para casos onde a busca possui palavras acentuadas. Ao que tudo indica podem haver conflitos de codificações de string quando utilizamos acentuação. O strlen() acaba por contar caracteres do tipo: á, é, í, como 2 caracteres ao invés de um só. Resolver isso é muito fácil. Basta adicionar a função utf8_decode() junto ao parâmetro. Você pode ver que no exemplo acima eu utilizei este comando para evitar possíveis erros com acentuação.
Podemos também utilizar a função mb_strlen() que explicarei em post futuro.
Espero que tenham gostado desta dica sobre strlen(). Para o próximo post explicarei o utf8_decode() e utf8_encode() e aos que tiverem interesse em buscar por si próprios deixo a dica de lerem um pouco no manual do php. Abs, e até a próxima.