How to abbreviate words in PHP?

9

I have common information such as people's names and addresses, and I need them to contain a maximum of 30 characters without cutting words.

Example:

'Avenida Natalino João Brescansin' => 'Av. Natalino J. Brescansin'
'Joaquim Rossafa Nascimento filho' => 'Joaquim Rossafa N. filho'
'Rua José Jesualdo Garcia Pessoa'  => 'R. José Jesualdo G. Pessoa'

How can I do this in PHP?

Is there a regular method or expression to solve this problem?

    
asked by anonymous 09.05.2016 / 15:43

3 answers

5

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.

    
09.05.2016 / 20:55
3

Come on, my dear ones,

When we are going to abbreviate our own names in PHP, the task is simple, we must note that here in Brazil the names that must be kept in full if possible should be the first name and the last name. Imagine the following name:

Antonio Fernades Coutinho

A pleasant result for the abbreviation of this case would be:

Antonio F. Coutinho

Omitting intermediate names can not always be seen with evil eyes:

Antonio Coutinho

But I'll put down the solution that includes the first abbreviation that holds only the abbreviated name initial followed by a period to indicate abbreviation.

//String com nome a ser abreviado
$name = "Antonio Fernandes Coutinho";

//como os nomes são separados por espaço em branco então vamos criar o array
//a partir dos espaços
$split_name = explode(" ",$name);


//so vamos abreviar o nome se 
//ele tiver pelo menos 2 sobrenomes
if(count($split_name) > 2){     

    //esse for inicia a partir da segunda
    // posição do array para o 
    //primeiro nome ser desconsiderado
    for($i=1;(count($split_name) - 1) > $i; $i++){

        //claro que como existem dos|de|da|das 
        //(Cristina DOS Santos) podemos 
        //omitir ou exibir sem abrevirar 
        //essas preposições, aqui no 
        //caso eu as mantenho sem alteração
        if(strlen($split_name[$i]) > 3){

            //aqui será feito a abreviação com apenas
            //a inicial da palavra a ser abreviada
            //seguida de ponto
            $split_name[$i] = substr($split_name[$i],0,1).".";  
        }       
    }   
}   

//aqui será impresso o nome resultante com a junção 
//do array em favor de se obter uma string colando as posições
//do array com espaços em branco!
echo implode(" ",$split_name);

// Antonio F. Coutinho

In order to abbreviate types of Addresses (Street, Avenue, Square, ...) you can create an array with the raw values "Avenue" as a key and "Av." as the value of this key, and abbreviate when it is found in the string, with a slight change in the above code you can do this.

It is clear that if the situation is more complex where it is necessary to sanitize a large set of limited combinations consider using regular expression.

Embrace

    
09.05.2016 / 18:42
2

If you have a database with a 20k register, create a Python script that will replace the words if they exceed 30 characters and then populate a table with the equivalences based on the id. Type, create a Dictionary ['Avenue': 'Av', 'Street': 'R.', etc], then give a select * in the database and iterate with a for loop on the list that returned, which asks for the len of the string and gives the replaces of the dictionary if you go through the 30 chars, create a basic dictionary and place to slice string with [0: x] if your dictionary does not do the complete work. Once you have both tables in your database it's theta link in php. I particularly do not know anything more powerful to process String than Python.

    
09.05.2016 / 22:11