Esta questão é uma referência para perguntas sobre a classificação de matrizes em PHP. É fácil pensar que seu caso em particular é único e digno de uma nova pergunta, mas a maioria é na verdade pequenas variações de uma das soluções desta página.
Se sua pergunta for encerrada como duplicada, solicite que ela seja reaberta apenas se você puder explicar por que ela difere significativamente de todas as opções abaixo.
Como faço para classificar uma matriz em PHP?
Como faço para classificar uma matriz complexa em PHP?
Como faço para classificar uma matriz de objetos em PHP?
Para a resposta prática usando as funções existentes do PHP, consulte 1., para a resposta acadêmica em detalhes sobre algoritmos de classificação (que funções do PHP implementam e que você pode precisar para casos realmente complexos), consulte 2.
Respostas:
Matrizes unidimensionais básicas
Funções de classificação aplicáveis:
sort
rsort
asort
arsort
natsort
natcasesort
ksort
krsort
A diferença entre eles é apenas se as associações de valor-chave são mantidas (as "
a
" funções), se classifica de baixo para alto ou reverso ("r
"), se classifica valores ou chaves ("k
") e como compara valores ("nat
" vs. normal). Veja http://php.net/manual/en/array.sorting.php para uma visão geral e links para mais detalhes.Matrizes multidimensionais, incluindo matrizes de objetos
Se você deseja classificar
$array
pela tecla 'foo' de cada entrada, precisa de uma função de comparação personalizada . Assort
funções acima e relacionadas funcionam com valores simples que eles sabem comparar e classificar. O PHP simplesmente não "sabe" o que fazer com um valor complexo como essearray('foo' => 'bar', 'baz' => 42)
; então você precisa contar.Para fazer isso, você precisa criar uma função de comparação . Essa função usa dois elementos e deve retornar
0
se esses elementos forem considerados iguais, um valor menor que0
se o primeiro valor for menor e um valor maior que0
se o primeiro valor for maior. É tudo o que é necessário:Freqüentemente, você desejará usar uma função anônima como retorno de chamada. Se você deseja usar um método ou método estático, consulte as outras maneiras de especificar um retorno de chamada no PHP .
Você então usa uma destas funções:
usort
uasort
uksort
Novamente, eles diferem apenas se mantêm associações de valores-chave e classificam por valores ou chaves. Leia a documentação deles para obter detalhes.
Exemplo de uso:
usort
pegará dois itens da matriz e chamará suacmp
função com eles. Assimcmp()
será chamado com$a
comoarray('foo' => 'bar', 'baz' => 42)
e$b
como outroarray('foo' => ..., 'baz' => ...)
. A função então retorna parausort
qual dos valores foi maior ou se eles foram iguais.usort
repete esse processo passando valores diferentes para$a
e$b
até que a matriz seja classificada. Acmp
função será chamada muitas vezes, pelo menos quantas vezes houver valores$array
, com diferentes combinações de valores para$a
e$b
sempre.Para se acostumar com essa ideia, tente o seguinte:
Tudo o que você fez foi definir uma maneira personalizada de comparar dois itens, é tudo o que você precisa. Isso funciona com todos os tipos de valores.
A propósito, isso funciona com qualquer valor, os valores não precisam ser matrizes complexas. Se você deseja fazer uma comparação personalizada, também pode fazê-lo em uma matriz simples de números.
sort
classifica por referência e não retorna nada útil!Observe que a matriz é classificada no local , não é necessário atribuir o valor de retorno a nada.
$array = sort($array)
substituirá a matriz portrue
, não por uma matriz classificada. Apenassort($array);
funciona.Comparações numéricas personalizadas
Se você deseja classificar pela
baz
chave, que é numérica, tudo que você precisa fazer é:Graças ao valor de MATH, isso retorna um valor <0, 0 ou> 0, dependendo de se
$a
é menor que, igual ou maior que$b
.Observe que isso não funcionará bem para
float
valores, pois eles serão reduzidos a umaint
e perderão precisão. Use explícita-1
,0
e1
valores de retorno em seu lugar.Objetos
Se você possui uma matriz de objetos, funciona da mesma maneira:
Funções
Você pode fazer qualquer coisa dentro de uma função de comparação, incluindo funções de chamada:
Cordas
Um atalho para a primeira versão de comparação de cadeias:
strcmp
é exatamente o que se esperacmp
aqui, ele retorna-1
,0
ou1
.Operador de nave espacial
O PHP 7 introduziu o operador de nave espacial , que unifica e simplifica igual / menor / maior que as comparações entre os tipos:
Classificando por vários campos
Se você deseja classificar principalmente por
foo
, mas sefoo
for igual para dois elementos, classifique porbaz
:Para aqueles familiarizados, isso é equivalente a uma consulta SQL com
ORDER BY foo, baz
.Veja também esta versão simplificada e simples de como criar uma função de comparação dinamicamente para um número arbitrário de chaves .
Classificando em uma ordem estática manual
Se você deseja classificar os elementos em uma "ordem manual", como "foo", "bar", "baz" :
Por todas as razões acima, se você estiver usando PHP 5.3 ou superior (e realmente deveria), use funções anônimas para obter um código mais curto e evitar que outra função global flutue:
É assim que a classificação de uma matriz multidimensional complexa pode ser simples. Novamente, pense em termos de ensinar PHP como saber qual dos dois itens é "maior" ; deixe o PHP fazer a classificação real.
Também para todas as opções acima, para alternar entre ordem crescente e decrescente, basta trocar os argumentos
$a
e$b
. Por exemplo:Classificando uma matriz com base em outra
E há o peculiar
array_multisort
, que permite classificar um array com base em outro:O resultado esperado aqui seria:
Use
array_multisort
para chegar lá:A partir do PHP 5.5.0, você pode usar
array_column
para extrair uma coluna de uma matriz multidimensional e classificar a matriz nessa coluna:A partir do PHP 7.0.0, você também pode extrair propriedades de uma matriz de objetos.
fonte
array_flip()
para fazer uma pesquisa de posição mais rápida, por exemplo, em$order[$a['foo']]
vez dearray_search($a['foo'], $order)
.Bem, a maioria dos métodos básicos já está coberta por deceze. Eu tentaria olhar para outros tipos de tipos.
Classificando com SPL
SplHeap
Resultado
SplMaxHeap
A classe SplMaxHeap fornece as principais funcionalidades de um heap, mantendo o máximo no topo.
SplMinHeap
Outros tipos de classificação
Tipo de bolha
Do artigo da Wikipedia sobre Bubble Sort:
Classificação da seleção
A partir do artigo da Wikipedia sobre tipo de seleção:
Classificação de inserção
No artigo da Wikipedia sobre Inserção, classifique:
Shellsort
Do artigo da Wikipedia sobre Shellsort:
Classificação de pente
A partir do artigo da Wikipedia sobre Comb tipo:
Mesclar classificação
A partir do artigo da Wikipedia sobre merge sort:
Ordenação rápida
Do artigo da Wikipedia sobre o Quicksort:
Classificação de permutação
A partir do artigo da Wikipedia sobre Permutation tipo:
Classificação Radix
A partir do artigo da Wikipedia sobre Radix tipo:
fonte
O(n^2)
as comparações se vamos usar apenas primeiro elemento como pivô)Classificação estável
Digamos que você tenha uma matriz como esta:
E agora você deseja classificar apenas na primeira letra:
O resultado é este:
O tipo não era estável!
O observador aguçado pode ter notado que o algoritmo de classificação de array (QuickSort) não produziu um resultado estável e que a ordem original entre as palavras da mesma primeira letra não foi preservada. Esse caso é trivial e deveríamos ter comparado toda a cadeia de caracteres, mas vamos supor que seu caso de uso seja mais complicado, como dois tipos consecutivos em campos diferentes que não devem cancelar o trabalho um do outro.
A transformação schwartziana
A transformação Schwartziana , também chamada de idioma decorar-classificar-undecorate, efetua uma classificação estável com um algoritmo de classificação inerentemente instável.
Primeiro, você decora cada elemento da matriz com outra matriz que compreende uma chave primária (o valor) e uma chave secundária (seu índice ou posição):
Isso transforma a matriz em isso:
Agora, ajustamos a etapa de comparação; comparamos a primeira letra novamente, mas, se forem iguais, a chave secundária será usada para manter a ordem original:
Posteriormente, decoremos:
O resultado final:
E a reutilização?
Você teve que reescrever sua função de comparação para trabalhar com os elementos da matriz transformados; você pode não querer editar suas delicadas funções de comparação, então aqui está um wrapper para a função de comparação:
Vamos escrever a etapa de classificação usando esta função:
Voila! Seu código de comparação original está de volta.
fonte
A partir do PHP 5.3 com fechamentos, também é possível usar um fechamento para determinar a ordem de sua classificação.
Por exemplo, assumindo que $ array é uma matriz de objetos que contêm uma propriedade de mês.
fonte
LINQ
No .NET, o LINQ é freqüentemente usado para classificação, o que fornece uma sintaxe muito mais agradável sobre as funções de comparação, especialmente quando os objetos precisam ser classificados por vários campos. Existem várias portas do LINQ para PHP, incluindo a biblioteca YaLinqo *. Com isso, as matrizes podem ser classificadas com uma única linha sem escrever funções de comparação complexas.
As comparações podem ser personalizadas ainda mais, passando um retorno de chamada como um segundo argumento, por exemplo:
Aqui
'$v->count'
está uma abreviação defunction ($v) { return $v->count; }
(qualquer um pode ser usado). Essas cadeias de métodos retornam iteradores, os iteradores podem ser transformados em matrizes adicionando->toArray()
no final, se necessário.Internamente,
orderBy
e métodos relacionados chamar funções de matriz de classificação apropriados (uasort
,krsort
,multisort
,usort
etc.).O LINQ contém muitos outros métodos inspirados no SQL: filtragem, agrupamento, junção, agregação etc. É mais adequado para casos em que transformações complexas em matrizes e objetos precisam ser executadas sem depender de bancos de dados.
* desenvolvido por mim, consulte o leia-me para obter mais detalhes e comparação com outras portas LINQ
fonte
Classificação multidimensional por valor-chave
Tipo natural de uma matriz multidimensional por um valor-chave e também mantém a ordem original (não embaralhe as chaves principais):
Caso de teste:
fonte
É muito conveniente classificar matrizes com a função classificada do Nspl :
Classificação básica
Classificando por resultado da função
Classificação da matriz multidimensional
Classificação da matriz de objetos
Classificando com uma função de comparação
Você pode ver todos esses exemplos aqui .
fonte
Se você deseja solicitar pelo valor da chave, pode fazer uma linha, elegante e clara. Isso será ordenado pelo preço crescente. Usa array_multisort e array_column.
para produzir
fonte
Esta página é muito abrangente, mas quero acrescentar um pouco mais sobre a incrível utilidade do operador de espaçonave (operador de comparação de três vias) - uma linda criança do PHP7 +.
Usando o operador da nave espacial para implementar várias condições de classificação
Isso faz grandes avanços na redução do inchaço do código e na melhoria da legibilidade.
Ao escrever sua função de classificação personalizada (
usort()
/uasort()
/uksort()
) para processar várias condições, você só precisa escrever matrizes balanceadas nos dois lados do operador e retornar o resultado. Não há mais blocos de condição aninhados ou vários retornos.Os elementos de ambos os lados do operador serão percorridos da esquerda para a direita, um de cada vez, e retornando a avaliação assim que um não empate for encontrado ou quando todos os elementos forem comparados.
Dados de amostra para minhas demonstrações:
Demonstrações (para evitar o inchaço da página Stackoverflow, consulte o link de demonstração das saídas):
Lógica de classificação:
flutuador ASC
Lógica de classificação:
ASC booleano
Lógica de classificação:
ASC natString
Essa sintaxe permite classificar valores, resultados funcionais, dados profundamente aninhados e direção da classificação de maneira elegante. Definitivamente, vale a pena colocar no seu cinto de ferramentas php ... nos casos em que você estiver processando dados que não são do banco de dados - porque é claro que o SQL seria uma técnica muito mais sensata.
A seu critério, a partir do PHP7.4, você pode usar a sintaxe da seta com essas funções anônimas. Mesmo script com sintaxe de seta .
fonte
Se alguém quiser uma solução mais simples para manipular matrizes, basta usar o pacote Laravel Collection, que possui uma função sortBy implementada que permite classificar as chaves de maneira simples.
ou seja, para classificar primeiro por a, depois b, então c, a cláusula correta seria
https://packagist.org/packages/tightenco/collect
fonte
Existem várias maneiras de classificar uma matriz. Vou mencionar alguns métodos para executar essa tarefa. Em primeiro lugar, darei uma matriz inteira que é chamada como '$ numbers'.
Essa é a maneira normal de criar uma matriz. Suponha que, eu quero classificar essa matriz em ordem crescente.Para isso, o método 'sort ()' pode ser usado.
Agora considere a saída disso,
Você pode ver que a matriz numérica impressa está classificada. Se você deseja que a matriz numérica seja classificada em ordem decrescente, o método 'rsort ()' pode ser usado para essa tarefa.
considere a saída ..
Agora, a matriz é classificada em ordem decrescente.
Então, agora eu quero classificar essa matriz em ordem crescente de acordo com o valor deles. O método 'asort ()' pode ser usado para isso.
Se você classificar a ordem decrescente de acordo com seu valor, o método 'arsort ()' poderá ser usado. Suponha que você queira classificar essa matriz de acordo com o valor da chave. Neste, o método 'ksort ()' pode ser usado.
Agora considere a saída.
Agora a matriz é classificada de acordo com seu valor-chave. Se você deseja classificar a matriz em ordem decrescente de acordo com seu valor-chave, o método 'krsort ()' pode ser usado.
Agora, a matriz associativa é classificada em ordem decrescente de acordo com seu valor-chave.
Se você está procurando por um array de array em ordem crescente ou decrescente, você pode criar um array em ordem crescente.
fonte
O mais simples é usar a função usort para classificar a matriz sem nenhum loop: Abaixo está um exemplo:
Isso será ordenado na ordem desejada:
Isso será ordenado em ordem crescente:
fonte