O PHP possui várias funções para ordenação de array.
Como a linguagem tem um sério problema quando trata-se de padronização de argumentos, algumas dessas funções são meio chatas para se usar e podem trazer surpresas desagradáveis.
Nesse artigo vou apresentar todas essas funções, para que você nem eu tenhamos problemas com elas.
O que me levou a escrever esse texto é o fato dessas funções receberem o array por referência. Isso é, modificam a variável diretamente e ao invés de retornar um array retornam bool.
Já perdi preciosos minutos com um código como esse:
$arr = [1, 2, 3]; // Não faça isso! $arr = sort($arr); echo $arr[0]; //Erro: $arr agora é boolean, não mais um array
Aliás, fico tentando imaginar um caso para verificar esse retorno. 🙂
sort e rsort
bool sort(array &$array[, int $sort_flags = SORT_REGULAR])
bool rsort(array &$array[, int $sort_flags = SORT_REGULAR])
A função sort ordena os valores do array do menor para o maior (ascendentemente), enquanto a função rsort ordena do maior para o menor (descendentemente).
Essas funções também removem as chaves do array, transformando-o em um array indexado numericamente.
Atenção ao protótipo, especialmente ao argumento que pede o array. Quando tiver um & na frente do nome do parâmetro, significa que ele é passado por referência.
Já o segundo parâmetro são opções de ordenação:
- SORT_REGULAR (default): compara os itens normalmente, sem modificar os tipos
- SORT_NUMERIC: compara os items numericamente
- SORT_STRING: compara os itens como strings
- SORT_LOCALE_STRING: compara os itens como string, utilizando regras de comparação de localização
- SORT_NATURAL: mesmo comportamento da função natsort, que compara e ordena as strings numa ordem natural
- SORT_FLAG_CASE: Combinado com as flags de string, pode ser usada para ordenar sem considerar maiúsculas e minúsculas
Exemplos
Comportamento padrão
<?php $fruits = ['Laranja', 'melancia', 'banana']; sort($fruits); var_dump($fruits); // Laranja, banana, melancia ?>
Saída:
array(3) {
[0]=>
string(7) "Laranja"
[1]=>
string(6) "banana"
[2]=>
string(8) "melancia"
}
Usando a flag SORT_FLAG_CASE
<?php $fruits = ['Laranja', 'melancia', 'banana']; sort($fruits, SORT_STRING|SORT_FLAG_CASE); var_dump($fruits); // banana, Laranja, melancia ?>
Saída:
array(3) {
[0]=>
string(6) "banana"
[1]=>
string(7) "Laranja"
[2]=>
string(8) "melancia"
}
asort e arsort
Essas funções tem o mesmo protótipo e fazem o mesmo que sort e rsort, com a diferença que elas mantém as associações entre chaves e valores.
Exemplo
<?php $info1 = $info2 = ['a' => 'd', 'b' => 'c']; sort($info1); asort($info2); echo "With sort: \n"; var_dump($info1); echo "With asort: \n"; var_dump($info2); ?>
saída:
With sort:
array(2) {
[0]=>
string(1) "c"
[1]=>
string(1) "d"
}
With asort:
array(2) {
["b"]=>
string(1) "c"
["a"]=>
string(1) "d"
}
ksort e krsort
Ainda com o mesmo protótipo de sort e rsort, essas funções comparam e ordenam as chaves do array, ao invés dos valores.
<?php $info = [ 'nome' => 'Josiel', 'idade' => 23, ]; ksort($info); var_dump($info); ?>
Saída:
array(2) {
["idade"]=>
int(23)
["nome"]=>
string(6) "Josiel"
}
natsort e natcasesort
bool natsort(array &$array)
bool natcasesort(array &$array)
As funções mostradas até agora comparam as strings do jeito das máquinas.
Isso é, se mandarmos ordenar um array como ['img20', 'img1', 'img2', 'img10']
elas nos retornarão ['img1', 'img10', 'img2', 'img20']
.
Para consertar isso deveríamos mandar um array do tipo ['img20', 'img01', 'img02', 'img10']
que ficaria ['img01', 'img02', 'img10', 'img20']
.
Já as funções natsort e natcasesort comparam e ordenam usando um algoritmo de ordenação natural.
A diferença entre elas é que a segunda é case-insensitive (maiúsculas e minúsculas não fazem diferença).
A função natsort é o mesmo que sort($array, SORT_NATURAL)
e natcasesort é o mesmo que sort($array, SORT_NATURAL|SORT_FLAG_CASE)
.
Exemplo
<?php $items1 = $items2 = ['img1', 'img2', 'img10', 'img20']; sort($items1); echo 'With sort: '.implode(', ', $items1)."\n"; natsort($items2); echo 'With natsort: '.implode(', ', $items2)."\n"; ?>
Saída:
With sort: img1, img10, img2, img20
With natsort: img1, img2, img10, img20
usort, uasort e uksort
bool usort(array &$array, callable $value_compare_func)
As funções apresentadas até agora usam um algoritmo do PHP para comparar os valores.
Essas três funções que vou falar agora fazem a mesma coisa que sort, asort e ksort, com a diferença que elas comparam os valores com uma função definida pelo usuário.
Elas tem o mesmo protótipo: array a ser ordenado e função de comparação.
A função de comparação recebe dois argumentos ($a e $b) e deve retornar um número menor que 0 se $a<$b
, 0 se $a==$b
e maior que 0 se $a>$b
.
Por que mudar o jeito que o PHP compara os valores das variáveis?
Simples: tem coisas que não tem como o PHP comparar, como por exemplo um objeto que representa uma fração.
Para sabermos se uma fração é menor, igual ou maior que outra tem que fazer várias tretas, e o PHP não sabe disso.
Exemplo
Vamos usar o exemplo da fração.
Primeiro criamos uma classe que representa uma fração. Ela terá um método “compareTo”, que vai retornar -1, 0 ou 1.
<?php class Fraction { public $numerator; public $denominator; public function __construct($numerator, $denominator) { $this->numerator = $numerator; $this->denominator = $denominator; } public function __tostring() { return $this->numerator.'/'.$this->denominator; } public function compareTo(Fraction $other) { if ($this->denominator === $other->denominator) { return $this->numerator <=> $other->numerator; } $num1 = $this->numerator * $other->denominator; $num2 = $other->numerator * $this->denominator; return $num1 <=> $num2; } }
*Aviso*: código não muito testado; se seu trabalho de faculdade for sobre frações em programação não confie nele.
Não vou me ater a explicar a classe acima, pois não é o foco do artigo.
Mas basicamente o método “compareTo” segue as regrinhas da matemática para verificar como uma fração se compara a outra.
Agora vamos criar um array de frações e ordená-lo:
$fractions = [ new Fraction(-4, 5), new Fraction(-3, 5), new Fraction(5, 7), new Fraction(9, 13), ]; echo 'Before uasort: '.implode(', ', $fractions)."\n"; uasort($fractions, function(Fraction $a, Fraction $b) { return $a->compareTo($b); }); echo 'After uasort: '.implode(', ', $fractions); ?>
Repare que a função que passamos para uasort é pequena. Quem faz o trabalho pesado é o método “compareTo”, de “Fraction”.
Isso porque esse método pode ser usado em outro lugar. Mas o que importa é que ele retorna exatamente o que a função uasort precisa.
Saída:
Before uasort: -4/5, -3/5, 5/7, 9/13
After uasort: -4/5, -3/5, 9/13, 5/7
Fim
Bom, é isso.
Espero que você tenha entendido o que quis passar nesse artigo, sobre as
funções para ordenação do PHP, um pouquinho de boa prática com o exemplo da fração e mostrando também um dos novos recursos do PHP 7, o spaceship operator.
Qualquer correção, crítica, elogio ou sugestão não esconda de mim. 🙂
Deixe aí nos comentários ou chama no Twitter que a gente conversa.
Até a próxima!