Sort phone numbers in a string

6

I have some mobile numbers, fixed and fixed, in a database, I used the function implode() to join them in the same string, getting like this:

(11) 3333-4353  (11) 98000-2222 (11) 3027-5555 (11) 97000-0333

What I want to do is sort them with preference for cell phones, that is, after the DDD (xx) numbers that have 9,8,7 in the front will be sorted at the beginning, what is the best way to do this? / p>     

asked by anonymous 11.06.2017 / 23:17

3 answers

6

Hello, use the function usort , with it you define a function that validates the order, the return of this function must be -1 or 1 . It is applied to arrays for comparison.

Here's how it would look:

<?php

$telefones = array(
    "(11) 3333-4353",
    "(11) 98000-2222",
    "(11) 3027-5555",
    "(11) 97000-0333",
);

function sortNumber($a, $b) {
    $a = preg_replace('/\D/', '', $a);
    $b = preg_replace('/\D/', '', $b);
    return ($a > $b) ? -1 : 1;
}

usort($telefones, 'sortNumber');

print_r($telefones);

?>

Result:

Array
(
    [0] => (11) 98000-2222
    [1] => (11) 97000-0333
    [2] => (11) 3333-4353
    [3] => (11) 3027-5555
)

An example of using this application within a class with a complete example:

<?php

class Telefones
{
    // Variável com os telefones
    private $telefones = array();

    // Construtor para enviar os telefones
    public function __construct($telefones)
    {
        if( is_array($telefones) )
        $this->telefones = $telefones;
    }

    // Funcão para ordenar
    public function ordernarTelefones()
    {
        $telefones = $this->telefones;      
        usort($telefones, array($this, 'sortNumber'));
        $this->telefones = $telefones;

        return $this;
    }

    // Função para resgatar os dados
    public function pegarTelefones()
    {
        return $this->telefones;
    }

    // Função auxiliar customizada com regra de ordenar
    private function sortNumber($a, $b)
    {
        $a = preg_replace('/\D/', '', $a);
        $b = preg_replace('/\D/', '', $b);
        return ($a > $b) ? -1 : 1;
    }

}

$array = array(
    "(11) 3333-4353",
    "(11) 98000-2222",
    "(11) 3027-5555",
    "(11) 97000-0333",
);

$telefones = new Telefones($array);

print_r(
    $telefones
        ->ordernarTelefones()
        ->pegarTelefones()
);

?>

Result:

Array
(
    [0] => (11) 98000-2222
    [1] => (11) 97000-0333
    [2] => (11) 3333-4353
    [3] => (11) 3027-5555
)
    
12.06.2017 / 00:26
4

If you are using php you can use ORDER BY DESC

example with MySQLi

    $sql=("SELECT coluna FROM Tabela ORDER BY coluna DESC"); 

    $result = mysqli_query($link,$sql);

    while($row = mysqli_fetch_assoc($result)) {
        $tels .=$row["cel_cli"]. " ";
    }

    echo $tels;

    
12.06.2017 / 01:10
1

There is no information on the origin of this data, if it is via the database the response of @Leo Caracciolo is sufficient. In general cases, such as where you are reading from the file you can use usort , as already indicated. However, if the DDD does not matter, you can omit them:

$telefones = [
    '(11) 3333-4353',
    '(11) 98000-2222',
    '(11) 3027-5555',
    '(11) 97000-0333',
    '(12) 99999-9999',
    '(12) 88888-8888',
    '(13) 11111-1111'

];


usort($telefones, function ($a, $b) {
    return strtr(substr($a, 5), ['-' => '']) <=> strtr(substr($b, 5), ['-' => '']);
});

This will result in:

array(7) {
  [0]=>
  string(14) "(11) 3027-5555"
  [1]=>
  string(14) "(11) 3333-4353"
  [2]=>
  string(15) "(13) 11111-1111"
  [3]=>
  string(15) "(12) 88888-8888"
  [4]=>
  string(15) "(11) 97000-0333"
  [5]=>
  string(15) "(11) 98000-2222"
  [6]=>
  string(15) "(12) 99999-9999"
}

The idea is very simple, according to Wikipedia all DDDs have exactly 2 digits and depart from 11 , so we use:

substr($valor, 5);

So that we get only what is from space, ie the first phone number on (* actually it will get anything on the 5th character, it does not matter if it is a phone number or not *)

Then we use:

strtr($valor, ['-' => ''])

In order to remove - , the use of strtr for str_replace is only performance, it tends to be a little faster in this case, in addition to personal preference, but you can use whichever one you prefer

So we use the spaceship operator, read more here , it returns which value is greater, a little similar to strcmp , however it only returns 1 , 0 or -1 .

If you want to list the opposite, use the basic mathematics of * (-1) , this will cause 1 to be -1 and vice versa, thus decreasing ordering:

usort($telefones, function ($a, $b) {
    return (strtr(substr($a, 5), ['-' => '']) <=> strtr(substr($b, 5), ['-' => ''])) * (-1);
});

Regarding @Bruno Rigolon's response this should be a bit faster, compare this and it on your machine.

  

/! \ It will not fetch the data, so it will "trust" any value, so if there is (aa) 123c5-abc3 , which is not a valid number, it will have no different action.

    
12.06.2017 / 08:10