I've implemented a generic function with some details (as in the case of the abbreviation of the last element of $list
- then you see that the abbreviation is not very pretty, but playing with the code a little improves this). The code is well commented, so I will not explain too much in text. Anything, ask in the comments.
The output of the program:
$ ./abrev.php
26: Av. Natalino J. Brescansin
24: Joaquim Rossafa N. Filho
27: R. José Jesualdo G. Pessoa
36: Il. Sr. Dr. Jabulani J. Joniscleyson
16: Praça da Igreja
42: Pç. da Igreja N. S. M. d. J. C. N. Senhor
The code:
#!/usr/bin/php
<?php
/* tamanho máximo da string */
$max_length = 30;
$table = array(
"Avenida" => "Av.",
"Rua" => "R.",
"Praça" => "Pç.",
"Ilustríssimo" => "Il.",
"Senhor" => "Sr.",
"Senhora" => "Sra.",
"Doutor" => "Dr.");
$list = array(
"Avenida Natalino João Brescansin",
"Joaquim Rossafa Nascimento Filho",
"Rua José Jesualdo Garcia Pessoa",
"Ilustríssimo Senhor Doutor Jabulani Jurango Joniscleyson",
"Praça da Igreja",
"Praça da Igreja Nossa Senhora Mãe de Jesus Cristo Nosso Senhor");
/* MAIN: aqui é feita a abreviação dos itens */
foreach($list as &$str) {
if(strlen($str) >= $max_length)
abrev($str);
printf("%d: %s\n", strlen($str), $str);
}
/* &$str
*
* Significa que o parametro será uma referência, não um cópia. As alterações
* que eu fizer em $str dentro de abrev() são aplicadas à $str "verdadeira".
*/
function abrev(&$str)
{
/* referencias globais */
global $table;
global $max_length;
/* verifica entradas tabuladas,
*
* a contagem com preg_match é usada como offset no proximo
* loop.
*/
$matches = 0;
foreach($table as $k => $v) {
/* /$k/i
* testa a chave (as definições completas) na string.
* preg_replace funciona na mesma base.
*/
if(preg_match("/$k/i", $str)) {
$matches++;
$str = preg_replace("/$k/i", $v, $str, 1);
}
}
/* aqui separa-se a string em palavras */
$s = explode(" ", $str);
/* Rua José Jesualdo Garcia Pessoa
* pos : 0 1 2 3 4
*
* matches = 1
* count() = 5
*
* inicio
* i = 5 - 2 = 3 (começa no Garcia, penultimo nome)
*
* fim
* i >= $matches + 1 = 1 + 1 = 2
* (segunda palavra depois da ultima abreviação tabelada)
*/
for($i = count($s) - 2; $i >= $matches + 1; $i--) {
/* \.$ testa se o ultimo caractere da string é um ponto.
* Se for, significa que já está abreviado, e se já é uma
* palavra abreviada, saímos do loop.
*/
if(preg_match("/\.$/", $s[$i])) break;
/* unset é importante pra 'n' não ficar com lixo */
unset($n);
/* a primeira letra da palavra atual */
$n[] = $s[$i][0];
$n[] = ".";
/* substituimos s[i] pela versão abreviada */
$s[$i] = implode("", $n);
/* testa o tamanho total da string */
if(full_length($s) <= $max_length) break;
}
/* junta tudo pra "retornar"... o parâmetro é por referência,
* não por cópia
*/
$str = implode(" ", $s);
}
/* Nada elegante... *Nada* eficiente... mas quebra o galho.
*
* Provavelmente tem como fazer a troca de uma palavra por sua primeira letra
* seguida por um ponto usando expressões regulares.
*/
function full_length(array $s)
{
$s = implode(" ", $s);
return strlen($s);
}
?>
Normally I am against posting ready codes, but since this is far from good for production ... You will have to work on it to improve efficiency, especially if you will use some engine data.